changes in files

This commit is contained in:
jain
2023-07-12 16:27:52 +05:30
36 changed files with 1523 additions and 198 deletions

View File

@ -2,15 +2,30 @@
from django.contrib import admin
"""Import django app"""
from .models import UserProfile, UserEmailOtp, UserPhoneOtp
from .models import UserEmailOtp, UserPhoneOtp, DefaultTaskImages, UserNotification, UserDelete
# Register your models here.
@admin.register(UserProfile)
class UserProfileAdmin(admin.ModelAdmin):
@admin.register(UserDelete)
class UserDeleteAdmin(admin.ModelAdmin):
"""User profile admin"""
list_display = ['user']
list_display = ['user', 'old_email', 'd_email']
def __str__(self):
return self.user__email
return self.user
@admin.register(UserNotification)
class UserNotificationAdmin(admin.ModelAdmin):
"""User profile admin"""
list_display = ['user', 'push_notification', 'email_notification', 'sms_notification']
def __str__(self):
return self.image_url
@admin.register(DefaultTaskImages)
class DefaultTaskImagesAdmin(admin.ModelAdmin):
"""User profile admin"""
list_display = ['task_name', 'image_url']
def __str__(self):
return self.image_url
@admin.register(UserEmailOtp)
class UserEmailOtpAdmin(admin.ModelAdmin):

View File

@ -1,6 +1,9 @@
"""Account app file"""
"""Import Django"""
from django.apps import AppConfig
class AccountConfig(AppConfig):
"""default configurations"""
default_auto_field = 'django.db.models.BigAutoField'
name = 'account'

View File

@ -0,0 +1,26 @@
# Generated by Django 4.2.2 on 2023-07-07 10:23
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0002_useremailotp_user_type'),
]
operations = [
migrations.CreateModel(
name='DefaultTaskImages',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('task_name', models.CharField(max_length=15)),
('image_url', models.URLField(blank=True, default=None, null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
],
options={
'db_table': 'default_task_image',
},
),
]

View File

@ -0,0 +1,31 @@
# Generated by Django 4.2.2 on 2023-07-10 09:24
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('account', '0003_defaulttaskimages'),
]
operations = [
migrations.CreateModel(
name='UserDelete',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('old_email', models.EmailField(blank=True, max_length=254, null=True, verbose_name='Original Email')),
('d_email', models.EmailField(blank=True, max_length=254, null=True, verbose_name='Dummy Email')),
('is_active', models.BooleanField(default=True)),
('reason', models.TextField(blank=True, max_length=500, null=True, verbose_name='Reason for Leaving')),
('created_at', models.DateTimeField(auto_now_add=True)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='delete_information_set', to=settings.AUTH_USER_MODEL)),
],
options={
'db_table': 'user_delete_information',
},
),
]

View File

@ -0,0 +1,31 @@
# Generated by Django 4.2.2 on 2023-07-10 12:40
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('account', '0004_userdelete'),
]
operations = [
migrations.CreateModel(
name='UserNotification',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('push_notification', models.BooleanField(default=True)),
('email_notification', models.BooleanField(default=True)),
('sms_notification', models.BooleanField(default=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='user_notification', to=settings.AUTH_USER_MODEL)),
],
options={
'db_table': 'user_notification',
},
),
]

View File

@ -1,6 +1,8 @@
"""Account module file"""
"""Django import"""
from django.db import models
import random
from django.contrib.auth.models import User
"""App import"""
from base.constants import USER_TYPE
# Create your models here.
@ -70,7 +72,71 @@ class UserEmailOtp(models.Model):
class Meta(object):
""" Meta information """
db_table = 'user_email_otp'
verbose_name = 'User Email OTP'
verbose_name_plural = 'User Email OTP'
def __str__(self):
"""return phone as an object"""
return self.email
class DefaultTaskImages(models.Model):
"""Default images upload in oss bucket"""
task_name = models.CharField(max_length=15)
image_url = models.URLField(null=True, blank=True, default=None)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta(object):
""" Meta information """
db_table = 'default_task_image'
def __str__(self):
"""return phone as an object"""
return self.task_name
class UserDelete(models.Model):
"""
User delete information
"""
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='delete_information_set')
"""Old email"""
old_email = models.EmailField(blank=True, null=True, verbose_name='Original Email')
"""Dummy email"""
d_email = models.EmailField(blank=True, null=True, verbose_name='Dummy Email')
is_active = models.BooleanField(default=True)
"""reason for leaving"""
reason = models.TextField(max_length=500, blank=True, null=True, verbose_name='Reason for Leaving')
created_at = models.DateTimeField(auto_now_add=True)
class Meta(object):
""" Meta information """
db_table = 'user_delete_information'
def __str__(self):
return self.user.email
class UserNotification(models.Model):
"""
User notification details
"""
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_notification')
"""Push Notification"""
push_notification = models.BooleanField(default=True)
"""Email Notification"""
email_notification = models.BooleanField(default=True)
"""SMS Notification"""
sms_notification = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta(object):
""" Meta information """
db_table = 'user_notification'
verbose_name = 'User Notification'
verbose_name_plural = 'User Notification'
def __str__(self):
return self.user.email

View File

@ -1,40 +1,47 @@
"""Account serializer"""
"""Django Imoprt"""
import random
from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework_simplejwt.tokens import RefreshToken
"""App import"""
from guardian.models import Guardian
from junior.models import Junior
from account.models import UserProfile, UserEmailOtp, UserPhoneOtp
from account.models import UserEmailOtp, DefaultTaskImages, UserDelete, UserNotification, UserPhoneOtp
from base.constants import GUARDIAN, JUNIOR, SUPERUSER
from django.db import transaction
from base.messages import ERROR_CODE_REQUIRED, ERROR_CODE, SUCCESS_CODE, STATUS_CODE_ERROR
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth import authenticate
from rest_framework import viewsets, status
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 junior_account_update, guardian_account_update
class GoogleSignInSerializer(serializers.Serializer):
"""Google login Serializer"""
email = serializers.EmailField()
class GoogleLoginSerializer(serializers.Serializer):
"""google login serializer"""
access_token = serializers.CharField(max_length=5000, required=True)
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 Meta(object):
"""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 +49,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)
@ -90,10 +83,9 @@ class ChangePasswordSerializer(serializers.Serializer):
def validate_current_password(self, value):
user = self.context
if self.context.password not in ('', None):
if user.check_password(value):
return value
raise serializers.ValidationError({"details":ERROR_CODE['2015']})
if self.context.password not in ('', None) and user.check_password(value):
return value
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')
@ -113,6 +105,7 @@ class ForgotPasswordSerializer(serializers.Serializer):
email = serializers.EmailField()
class SuperUserSerializer(serializers.ModelSerializer):
"""Super admin serializer"""
user_type = serializers.SerializerMethodField('get_user_type')
def get_user_type(self, obj):
@ -138,9 +131,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,9 +154,9 @@ 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',
'created_at', 'updated_at', 'user_type']
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', 'country_name']
class JuniorSerializer(serializers.ModelSerializer):
@ -176,7 +173,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,9 +190,9 @@ 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',
'updated_at', 'user_type']
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', 'country_name']
class EmailVerificationSerializer(serializers.ModelSerializer):
"""Email verification serializer"""
@ -201,3 +201,89 @@ class EmailVerificationSerializer(serializers.ModelSerializer):
model = UserEmailOtp
fields = '__all__'
class DefaultTaskImagesSerializer(serializers.ModelSerializer):
"""Update Password after verification"""
class Meta(object):
"""Meta info"""
model = DefaultTaskImages
fields = ['task_name', 'image_url']
def create(self, validated_data):
data = DefaultTaskImages.objects.create(**validated_data)
return data
class DefaultTaskImagesDetailsSerializer(serializers.ModelSerializer):
"""Update Password after verification"""
class Meta(object):
"""Meta info"""
model = DefaultTaskImages
fields = '__all__'
class UserDeleteSerializer(serializers.ModelSerializer):
"""User Delete Serializer"""
class Meta(object):
"""Meta Information"""
model = UserDelete
fields = ['reason']
def create(self, validated_data):
user = self.context['user']
user_type = str(self.context['user_type'])
data = validated_data.get('reason')
passwd = self.context['password']
random_num = random.randint(0,10000)
user_tb = User.objects.filter(id=user.id).last()
if user_tb and user_tb.check_password(passwd):
user_type_data = UserEmailOtp.objects.filter(email=user.email).last()
if user_type == '1' and user_type_data.user_type == '1':
junior_account_update(user_tb)
elif user_type == '2' and user_type_data.user_type == '2':
guardian_account_update(user_tb)
else:
raise serializers.ValidationError({"details":ERROR_CODE['2030'],"code":"400", "status":"failed"})
user_tb.email = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower()
user_tb.username = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower()
user_tb.password = 'None'
d_email = user_tb.email
o_mail = user.email
instance = UserDelete.objects.create(user=user_tb, d_email=d_email, old_email=o_mail,
is_active=True, reason=data)
user_tb.save()
return instance
else:
raise serializers.ValidationError({"details": ERROR_CODE['2031'], "code": "400", "status": "failed"})
class UserNotificationSerializer(serializers.ModelSerializer):
"""User Notification serializer"""
class Meta(object):
"""Meta info"""
model = UserNotification
fields = '__all__'
class UpdateUserNotificationSerializer(serializers.ModelSerializer):
"""Update User Notification serializer"""
class Meta(object):
"""Meta info"""
model = UserNotification
fields = ['push_notification', 'email_notification', 'sms_notification']
def create(self, validated_data):
instance = UserNotification.objects.filter(user=self.context).last()
if instance:
instance.push_notification = validated_data.get('push_notification',instance.push_notification)
instance.email_notification = validated_data.get('email_notification', instance.email_notification)
instance.sms_notification = validated_data.get('sms_notification', instance.sms_notification)
instance.save()
else:
instance = UserNotification.objects.create(user=self.context)
return instance
class UserPhoneOtpSerializer(serializers.ModelSerializer):
"""User Phone serializers"""
class Meta(object):
"""Meta info"""
model = UserPhoneOtp
fields = '__all__'

View File

@ -1,3 +1,5 @@
"""Test cases file of account"""
"""Django import"""
from django.test import TestCase
# Create your tests here.

View File

@ -1,26 +1,47 @@
""" Urls files"""
"""Django import"""
from django.urls import path, include
from rest_framework.decorators import api_view
"""Third party import"""
from rest_framework import routers
"""Import view functions"""
from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVerification, ReSendEmailOtp,
ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage)
ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage,
GoogleLoginViewSet, SigninWithApple, ProfileAPIViewSet, UploadImageAPIViewSet,
DefaultImageAPIViewSet, DeleteUserProfileAPIViewSet, UserNotificationAPIViewSet,
UpdateUserNotificationAPIViewSet)
"""Router"""
router = routers.SimpleRouter()
"""API End points with router"""
router.register('user', UserLogin, basename='user')
"""super admin login"""
router.register('admin', UserLogin, basename='admin')
# router.register('google-login', GoogleLoginAPIViewset, basename='admin')
"""google login end point"""
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')
"""email verification end point"""
router.register('user-email-verification', UserEmailVerification, basename='user-email-verification')
"""Resend email otp end point"""
router.register('resend-email-otp', ReSendEmailOtp, basename='resend-email-otp')
"""Profile end point"""
router.register('profile', ProfileAPIViewSet, basename='profile')
"""Upload default task image end point"""
router.register('upload-default-task-image', UploadImageAPIViewSet, basename='upload-default-task-image')
"""Fetch default task image end point"""
router.register('default-task-image', DefaultImageAPIViewSet, basename='default-task-image')
"""Delete user account"""
router.register('delete', DeleteUserProfileAPIViewSet, basename='delete')
"""user account notification"""
router.register('user-notification', UserNotificationAPIViewSet, basename='user-notification')
"""update user account notification"""
router.register('update-user-notification', UpdateUserNotificationAPIViewSet, basename='update-user-notification')
"""Define url pattern"""
urlpatterns = [
path('api/v1/', include(router.urls)),
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'),
]

View File

@ -1,11 +1,39 @@
"""Account utils"""
"""Third party Django app"""
"""Import django"""
from django.conf import settings
from rest_framework import viewsets, status
from rest_framework.response import Response
"""Third party Django app"""
from templated_email import send_templated_mail
import jwt
from datetime import datetime
from calendar import timegm
from uuid import uuid4
import secrets
from junior.models import Junior
from guardian.models import Guardian
def junior_account_update(user_tb):
"""junior account delete"""
junior_data = Junior.objects.filter(auth__email=user_tb.email).first()
if junior_data:
junior_data.is_active = False
junior_data.is_verified = False
junior_data.guardian_code = '{}'
junior_data.save()
def guardian_account_update(user_tb):
"""update guardian account after delete the user account"""
guardian_data = Guardian.objects.filter(user__email=user_tb.email).first()
if guardian_data:
guardian_data.is_active = False
guardian_data.is_verified = False
guardian_data.save()
jun_data = Junior.objects.filter(guardian_code__icontains=str(guardian_data.guardian_code))
for data in jun_data:
data.guardian_code.remove(guardian_data.guardian_code)
data.save()
def send_otp_email(recipient_email, otp):
"""Send otp on email with template"""
from_email = settings.EMAIL_FROM_ADDRESS
recipient_list = [recipient_email]
send_templated_mail(
@ -21,8 +49,8 @@ def send_otp_email(recipient_email, otp):
def custom_response(detail, data=None, response_status=status.HTTP_200_OK):
"""Custom response code"""
if not data:
"""when data is none"""
data = None
return Response({"data": data, "message": detail, "status": "success", "code": response_status})
@ -34,5 +62,62 @@ def custom_error_response(detail, response_status):
:return: Json response
"""
if not detail:
"""when details is empty"""
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 = {}
"""Update data dictionary"""
data.update({
'token_type': token_type,
'iss': 'your_site_url',
'iat': timegm(datetime.utcnow().utctimetuple()),
'jti': uuid4().hex
})
"""Access and Refresh token"""
TOKEN_TYPE = ["access", "refresh"]
if token_type == TOKEN_TYPE[1]:
"""Refresh token"""
exp = now_time + settings.SIMPLE_JWT['REFRESH_TOKEN_LIFETIME']
else:
"""access token"""
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()
"""generate access token"""
access = generate_jwt_token('access', now_time, data)
"""generate refresh token"""
refresh = generate_jwt_token('refresh', now_time, data)
return {
'access': access,
'refresh': refresh
}

View File

@ -1,64 +1,170 @@
"""Account view """
"""Django import"""
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
"""App Import"""
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
from account.models import UserProfile, UserPhoneOtp, UserEmailOtp
from account.models import UserProfile, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification
from django.contrib.auth.models import User
"""Account serializer"""
from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer,
ForgotPasswordSerializer, ResetPasswordSerializer, ChangePasswordSerializer,
GoogleSignInSerializer, UpdateGuardianImageSerializer, UpdateJuniorProfileImageSerializer)
GoogleLoginSerializer, UpdateGuardianImageSerializer, UpdateJuniorProfileImageSerializer,
DefaultTaskImagesSerializer, DefaultTaskImagesDetailsSerializer, UserDeleteSerializer,
UserNotificationSerializer, UpdateUserNotificationSerializer, UserPhoneOtpSerializer)
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 junior.serializers import JuniorProfileSerializer
from guardian.serializers import GuardianProfileSerializer
class GoogleLoginMixin:
"""google login mixin"""
def google_login(self, request):
"""google login function"""
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")
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)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
class ChangePasswordAPIView(views.APIView):
serializer_class = ChangePasswordSerializer
permission_classes = [IsAuthenticated]
def post(self, request):
serializer = ChangePasswordSerializer(context=request.user, data=request.data)
@ -96,9 +202,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)
@ -106,6 +218,8 @@ class ForgotPasswordAPIView(views.APIView):
class SendPhoneOtp(viewsets.ModelViewSet):
"""Send otp on phone"""
queryset = UserPhoneOtp.objects.all()
serializer_class = UserPhoneOtpSerializer
def create(self, request, *args, **kwargs):
otp = generate_otp()
phone_number = self.request.data['phone']
@ -121,6 +235,8 @@ class SendPhoneOtp(viewsets.ModelViewSet):
class UserPhoneVerification(viewsets.ModelViewSet):
"""Send otp on phone"""
queryset = UserPhoneOtp.objects.all()
serializer_class = UserPhoneOtpSerializer
def list(self, request, *args, **kwargs):
try:
phone_data = UserPhoneOtp.objects.filter(phone=self.request.GET.get('phone'),
@ -199,6 +315,7 @@ class UserLogin(viewsets.ViewSet):
class UserEmailVerification(viewsets.ModelViewSet):
"""User Email verification"""
serializer_class = EmailVerificationSerializer
queryset = UserEmailOtp.objects.all()
def list(self, request, *args, **kwargs):
try:
@ -206,6 +323,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':
@ -220,7 +346,8 @@ class UserEmailVerification(viewsets.ModelViewSet):
guardian_data.save()
refresh = RefreshToken.for_user(user_obj)
access_token = str(refresh.access_token)
return custom_response(SUCCESS_CODE['3011'], {"auth_token":access_token}, response_status=status.HTTP_200_OK)
return custom_response(SUCCESS_CODE['3011'], {"auth_token":access_token},
response_status=status.HTTP_200_OK)
else:
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
@ -229,14 +356,108 @@ class UserEmailVerification(viewsets.ModelViewSet):
class ReSendEmailOtp(viewsets.ModelViewSet):
"""Send otp on phone"""
queryset = UserEmailOtp.objects.all()
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)
else:
return custom_error_response(ERROR_CODE["2023"], response_status=status.HTTP_400_BAD_REQUEST)
class ProfileAPIViewSet(viewsets.ModelViewSet):
"""Profile viewset"""
queryset = User.objects.all()
serializer_class = JuniorProfileSerializer
def list(self, request, *args, **kwargs):
"""profile view"""
if str(self.request.GET.get('user_type')) == '1':
junior_data = Junior.objects.filter(auth=self.request.user).last()
if junior_data:
serializer = JuniorProfileSerializer(junior_data)
if str(self.request.GET.get('user_type')) == '2':
guardian_data = Guardian.objects.filter(user=self.request.user).last()
if guardian_data:
serializer = GuardianProfileSerializer(guardian_data)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
class UploadImageAPIViewSet(viewsets.ModelViewSet):
"""Profile viewset"""
queryset = DefaultTaskImages.objects.all()
serializer_class = DefaultTaskImagesSerializer
def create(self, request, *args, **kwargs):
"""profile view"""
image_data = request.data['image_url']
filename = f"default_task_images/{image_data.name}"
image = upload_image_to_alibaba(image_data, filename)
image_data = image
request.data['image_url'] = image_data
serializer = DefaultTaskImagesSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
return custom_error_response(serializer.error, response_status=status.HTTP_400_BAD_REQUEST)
class DefaultImageAPIViewSet(viewsets.ModelViewSet):
"""Profile viewset"""
queryset = DefaultTaskImages.objects.all()
serializer_class = DefaultTaskImagesDetailsSerializer
def list(self, request, *args, **kwargs):
"""profile view"""
queryset = DefaultTaskImages.objects.all()
serializer = DefaultTaskImagesSerializer(queryset, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
class DeleteUserProfileAPIViewSet(viewsets.GenericViewSet):
""" Delete user API view set """
@action(detail=False, methods=['POST'], url_path='user-account',serializer_class=UserDeleteSerializer,
permission_classes=[IsAuthenticated])
def account(self, request):
user_type = str(request.data['user_type'])
password = request.data['password']
serializer = self.get_serializer(data=request.data, context={'request': request, 'user': request.user,
'user_type':user_type,
'password':password})
if serializer.is_valid():
serializer.save()
return custom_response(SUCCESS_CODE['3005'], response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
class UserNotificationAPIViewSet(viewsets.ModelViewSet):
"""notification viewset"""
queryset = UserNotification.objects.all()
serializer_class = UserNotificationSerializer
def list(self, request, *args, **kwargs):
"""profile view"""
queryset = self.queryset.filter(user=request.user)
serializer = UserNotificationSerializer(queryset, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
class UpdateUserNotificationAPIViewSet(viewsets.ModelViewSet):
"""Update notification viewset"""
queryset = UserNotification.objects.all()
serializer_class = UpdateUserNotificationSerializer
def create(self, request, *args, **kwargs):
"""profile view"""
serializer = UpdateUserNotificationSerializer(data=request.data,
context=request.user)
if serializer.is_valid():
serializer.save()
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
return custom_error_response(serializer.error, response_status=status.HTTP_400_BAD_REQUEST)

View File

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

View File

@ -45,11 +45,16 @@ 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",
"2030": "Use correct user type and token",
"2031":"Invalid password"
}
SUCCESS_CODE = {
# Success code for password
@ -61,7 +66,7 @@ SUCCESS_CODE = {
# Success code for password reset
"3004": "Password reset link has been sent to your email address",
# Success code for link verified
"3005": "Your link has been verified, it's valid",
"3005": "Your account is deleted successfully.",
# Success code for password reset
"3006": "Your password has been reset successfully.",
# Success code for password update
@ -78,7 +83,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 = {

View File

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

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

View 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),
),
]

View 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),
),
]

View File

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

View 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),
),
]

View 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),
),
]

View File

@ -3,7 +3,9 @@
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
"""Add user model"""
User = get_user_model()
# Create your models here.
@ -15,7 +17,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 +43,37 @@ class Guardian(models.Model):
def __str__(self):
"""Return email id"""
return f'{self.user}'
class JuniorTask(models.Model):
"""Junior Task details model"""
guardian = models.ForeignKey(Guardian, on_delete=models.CASCADE, related_name='guardian', verbose_name='Guardian')
"""task details"""
task_name = models.CharField(max_length=100)
task_description = models.CharField(max_length=500)
"""points of the task"""
points = models.IntegerField(default=TASK_POINTS)
due_date = models.DateField(auto_now_add=False, null=True, blank=True)
"""Images of task"""
default_image = models.URLField(null=True, blank=True, default=None)
image = models.URLField(null=True, blank=True, default=None)
"""associated junior with the task"""
junior = models.ForeignKey(Junior, on_delete=models.CASCADE, related_name='junior', verbose_name='Junior')
"""task status"""
task_status = models.CharField(choices=TASK_STATUS, max_length=15, default=PENDING)
"""task stage"""
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}'

View File

@ -7,11 +7,13 @@ 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 account.models import UserProfile, UserEmailOtp
from .models import Guardian, JuniorTask
from account.models import UserProfile, UserEmailOtp, UserNotification
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
from junior.models import Junior, JuniorPoints
class UserSerializer(serializers.ModelSerializer):
"""User serializer"""
auth_token = serializers.SerializerMethodField('get_auth_token')
@ -34,11 +36,13 @@ class UserSerializer(serializers.ModelSerializer):
try:
"""Create user profile"""
user = User.objects.create_user(username=email, email=email, password=password)
UserProfile.objects.create(user=user, user_type=user_type)
UserNotification.objects.create(user=user)
if user_type == '1':
Junior.objects.create(auth=user)
Junior.objects.create(auth=user, junior_code=''.join([str(random.randrange(9)) for _ in range(6)]),
referral_code=''.join([str(random.randrange(9)) for _ in range(6)]))
if user_type == '2':
Guardian.objects.create(user=user)
Guardian.objects.create(user=user, guardian_code=''.join([str(random.randrange(9)) for _ in range(6)]),
referral_code=''.join([str(random.randrange(9)) for _ in range(6)]))
return user
except Exception as e:
"""Error handling"""
@ -63,7 +67,7 @@ class CreateGuardianSerializer(serializers.ModelSerializer):
family_name = serializers.CharField(max_length=100, required=False)
dob = serializers.DateField(required=False)
referral_code = serializers.CharField(max_length=100, required=False)
image = serializers.ImageField(required=False)
image = serializers.URLField(required=False)
class Meta(object):
"""Meta info"""
@ -86,18 +90,14 @@ class CreateGuardianSerializer(serializers.ModelSerializer):
def create(self, validated_data):
"""Create guardian profile"""
# 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 (guardian_data or junior_data):
# raise serializers.ValidationError({"details": ERROR_CODE['2012']})
user = User.objects.filter(username=self.context['user']).last()
if user:
"""Save first and last name of guardian"""
if self.context.get('first_name') != '' and self.context.get('last_name') != '':
user.first_name = self.context.get('first_name', user.first_name)
user.last_name = self.context.get('last_name', user.last_name)
user.save()
if self.context.get('first_name') != '' and self.context.get('first_name') is not None:
user.first_name = self.context.get('first_name')
if self.context.get('last_name') != '' and self.context.get('last_name') is not None:
user.last_name = self.context.get('last_name')
user.save()
"""Create guardian data"""
guardian, created = Guardian.objects.get_or_create(user=self.context['user'])
if created:
@ -115,17 +115,14 @@ class CreateGuardianSerializer(serializers.ModelSerializer):
guardian.passcode = validated_data.get('passcode', guardian.passcode)
guardian.country_name = validated_data.get('country_name', guardian.country_name)
guardian.referral_code_used = validated_data.get('referral_code_used', guardian.referral_code_used)
guardian.image = validated_data.get('image', guardian.image)
"""Complete profile of the junior if below all data are filled"""
complete_profile_field = all([guardian.phone, guardian.gender, guardian.family_name, guardian.country_name,
guardian.dob, guardian.country_code, user.first_name, user.last_name])
complete_profile_field = all([guardian.phone, guardian.gender, guardian.country_name,
guardian.dob, guardian.country_code, user.first_name, user.last_name,
user.email, guardian.image])
guardian.is_complete_profile = False
if complete_profile_field:
guardian.is_complete_profile = True
image = validated_data.pop('image', None)
if image:
filename = f"images/{image.name}"
image_url = upload_image_to_alibaba(image, filename)
guardian.image = image_url
guardian.save()
return guardian
@ -134,3 +131,115 @@ class CreateGuardianSerializer(serializers.ModelSerializer):
with transaction.atomic():
instance = super().save(**kwargs)
return instance
class TaskSerializer(serializers.ModelSerializer):
"""Task serializer"""
class Meta(object):
"""Meta info"""
model = JuniorTask
fields = ['task_name','task_description','points', 'due_date', 'junior', 'default_image']
def create(self, validated_data):
"""create default task image 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):
junior = JuniorDetailSerializer()
class Meta(object):
"""Meta info"""
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):
"""Top junior serializer"""
junior = JuniorDetailSerializer()
position = serializers.IntegerField()
class Meta:
"""Meta info"""
model = JuniorPoints
fields = ['id', 'junior', 'total_task_points', 'position', 'created_at', 'updated_at']
def to_representation(self, instance):
"""Convert instance to representation"""
representation = super().to_representation(instance)
representation['position'] = instance.position
return representation
class GuardianProfileSerializer(serializers.ModelSerializer):
"""junior serializer"""
email = serializers.SerializerMethodField('get_auth')
first_name = serializers.SerializerMethodField('get_first_name')
last_name = serializers.SerializerMethodField('get_last_name')
total_count = serializers.SerializerMethodField('get_total_count')
complete_field_count = serializers.SerializerMethodField('get_complete_field_count')
notification_count = serializers.SerializerMethodField('get_notification_count')
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
def get_total_count(self, obj):
"""total fields count"""
return 9
def get_complete_field_count(self, obj):
"""total filled fields count"""
total_field_list = [obj.user.first_name, obj.user.last_name, obj.user.email, obj.country_name, obj.country_code,
obj.phone, obj.gender, obj.dob, obj.image]
total_complete_field = [data for data in total_field_list if data != '' and data is not None]
return len(total_complete_field)
def get_notification_count(self, obj):
"""total notification count"""
return 0
class Meta(object):
"""Meta info"""
model = Guardian
fields = ['id', 'email', 'first_name', 'last_name', 'country_name','country_code', 'phone', 'gender', 'dob',
'guardian_code', 'notification_count', 'total_count', 'complete_field_count', 'referral_code',
'is_active', 'is_complete_profile', 'created_at', 'image',
'updated_at']

View File

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

View File

@ -1,13 +1,22 @@
"""Utiles file of guardian"""
"""Django import"""
import oss2
from django.conf import settings
import tempfile
def upload_image_to_alibaba(image, filename):
"""upload image on oss alibaba bucket"""
# Save the image object to a temporary file
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
"""write image in temporary file"""
temp_file.write(image.read())
"""auth of bucket"""
auth = oss2.Auth(settings.ALIYUN_OSS_ACCESS_KEY_ID, settings.ALIYUN_OSS_ACCESS_KEY_SECRET)
"""fetch bucket details"""
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}"
"""create perfect url for image"""
new_filename = filename.replace(' ', '%20')
return f"https://{settings.ALIYUN_OSS_BUCKET_NAME}.{settings.ALIYUN_OSS_ENDPOINT}/{new_filename}"

View File

@ -2,47 +2,173 @@
"""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 junior.models import Junior
from account.models import UserEmailOtp
from .serializers import (UserSerializer, CreateGuardianSerializer, TaskSerializer, TaskDetailsSerializer,
TopJuniorSerializer)
from .models import Guardian, JuniorTask
from junior.models import Junior, JuniorPoints
from junior.serializers import JuniorDetailSerializer
from account.models import UserEmailOtp, UserNotification
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"""
queryset = User.objects.all()
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"""
queryset = Guardian.objects.all()
serializer_class = CreateGuardianSerializer
permission_classes = [IsAuthenticated]
def create(self, request, *args, **kwargs):
"""Create guardian profile"""
data = request.data
image = request.data.get('image')
image_url = ''
if image:
filename = f"images/{image.name}"
image_url = upload_image_to_alibaba(image, filename)
data = {"image":image_url}
serializer = CreateGuardianSerializer(context={"user":request.user,
"first_name":request.data.get('first_name', ''),
"last_name": request.data.get('last_name',' ')},
data=request.data)
"first_name":request.data.get('first_name'),
"last_name": request.data.get('last_name'),
"image":image_url},
data=data)
if serializer.is_valid():
"""save serializer"""
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
queryset = JuniorTask.objects.all()
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
queryset = JuniorTask.objects.all()
def list(self, request, *args, **kwargs):
"""Create guardian profile"""
status_value = self.request.GET.get('status')
if str(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
queryset = JuniorTask.objects.all()
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
queryset = JuniorTask.objects.all()
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]
queryset = JuniorPoints.objects.all()
def get_serializer_context(self):
context = super().get_serializer_context()
context.update({'view': self})
return context
def list(self, request, *args, **kwargs):
"""Fetch junior list of those who complete their tasks"""
junior_total_points = self.get_queryset().order_by('-total_task_points')
# Update the position field for each JuniorPoints object
for index, junior in enumerate(junior_total_points):
junior.position = index + 1
junior.save()
serializer = self.get_serializer(junior_total_points, many=True)
return custom_response(serializer.data, response_status=status.HTTP_200_OK)

View File

@ -2,13 +2,22 @@
"""Third party Django app"""
from django.contrib import admin
"""Import Django app"""
from .models import Junior
from .models import Junior, JuniorPoints
# Register your models here.
@admin.register(Junior)
class JuniorAdmin(admin.ModelAdmin):
"""Junior Admin"""
list_display = ['auth']
list_display = ['auth', 'guardian_code']
def __str__(self):
"""Return email id"""
return self.auth__email
@admin.register(JuniorPoints)
class JuniorPointsAdmin(admin.ModelAdmin):
"""Junior Points Admin"""
list_display = ['junior', 'total_task_points', 'position']
def __str__(self):
"""Return email id"""
return self.junior.auth.email

View 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),
),
]

View File

@ -0,0 +1,28 @@
# Generated by Django 4.2.2 on 2023-07-09 12:40
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('junior', '0007_alter_junior_image'),
]
operations = [
migrations.CreateModel(
name='JuniorPoints',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('total_task_points', models.IntegerField(blank=True, default=0, null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('junior', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='junior_points', to='junior.junior')),
],
options={
'verbose_name': 'Junior Task Points',
'db_table': 'junior_task_points',
},
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2023-07-10 07:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('junior', '0008_juniorpoints'),
]
operations = [
migrations.AddField(
model_name='juniorpoints',
name='position',
field=models.IntegerField(blank=True, default=99999, null=True),
),
]

View File

@ -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)
@ -41,3 +41,23 @@ class Junior(models.Model):
def __str__(self):
"""Return email id"""
return f'{self.auth}'
class JuniorPoints(models.Model):
"""Junior model"""
junior = models.OneToOneField(Junior, on_delete=models.CASCADE, related_name='junior_points')
"""Contact details"""
total_task_points = models.IntegerField(blank=True, null=True, default=0)
"""position of the junior"""
position = models.IntegerField(blank=True, null=True, default=99999)
"""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_points'
verbose_name = 'Junior Task Points'
def __str__(self):
"""Return email id"""
return f'{self.junior.auth}'

View File

@ -5,10 +5,11 @@ from django.contrib.auth.models import User
from django.db import transaction
import random
"""Import django app"""
from junior.models import Junior
from junior.models import Junior, JuniorPoints
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"""
@ -35,7 +36,7 @@ class CreateJuniorSerializer(serializers.ModelSerializer):
dob = serializers.DateField(required=False)
referral_code = serializers.CharField(max_length=100, required=False)
guardian_code = ListCharField(required=False)
image = serializers.ImageField(required=False)
image = serializers.URLField(required=False)
class Meta(object):
"""Meta info"""
@ -58,19 +59,15 @@ 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"""
if self.context.get('first_name') != '' and self.context.get('last_name') != '':
user.first_name = self.context.get('first_name', user.first_name)
user.last_name = self.context.get('last_name', user.last_name)
user.save()
if self.context.get('first_name') != '' and self.context.get('first_name') is not None:
user.first_name = self.context.get('first_name')
if self.context.get('last_name') != '' and self.context.get('last_name') is not None:
user.last_name = self.context.get('last_name')
user.save()
"""Create junior data"""
junior, created = Junior.objects.get_or_create(auth=self.context['user'])
if created:
@ -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)
@ -89,16 +89,14 @@ class CreateJuniorSerializer(serializers.ModelSerializer):
junior.phone = validated_data.get('phone', junior.phone)
junior.country_code = validated_data.get('country_code', junior.country_code)
junior.referral_code_used = validated_data.get('referral_code_used', junior.referral_code_used)
junior.image = validated_data.get('image', junior.image)
"""Complete profile of the junior if below all data are filled"""
complete_profile_field = all([junior.phone, junior.gender, junior.country_name,
junior.dob, junior.country_code, user.first_name, user.last_name])
complete_profile_field = all([junior.phone, junior.gender, junior.country_name, junior.image,
junior.dob, junior.country_code, user.first_name, user.last_name,
user.email])
junior.is_complete_profile = False
if complete_profile_field:
junior.is_complete_profile = True
if image:
filename = f"images/{image.name}"
image_url = upload_image_to_alibaba(image, filename)
junior.image = image_url
junior.save()
return junior
@ -107,3 +105,136 @@ 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')
position = serializers.SerializerMethodField('get_position')
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_position(self, obj):
data = JuniorPoints.objects.filter(junior=obj).last()
if data:
return data.position
return 99999
def get_points(self, obj):
data = sum(JuniorTask.objects.filter(junior=obj, task_status=COMPLETED).values_list('points', flat=True))
return data
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', 'position']
class JuniorProfileSerializer(serializers.ModelSerializer):
"""junior serializer"""
email = serializers.SerializerMethodField('get_auth')
first_name = serializers.SerializerMethodField('get_first_name')
last_name = serializers.SerializerMethodField('get_last_name')
notification_count = serializers.SerializerMethodField('get_notification_count')
total_count = serializers.SerializerMethodField('get_total_count')
complete_field_count = serializers.SerializerMethodField('get_complete_field_count')
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
def get_notification_count(self, obj):
"""total notification count"""
return 0
def get_total_count(self, obj):
"""total fields count"""
return 9
def get_complete_field_count(self, obj):
"""total filled fields count"""
field_list = [obj.auth.first_name, obj.auth.last_name, obj.auth.email, obj.country_name, obj.country_code,
obj.phone, obj.gender, obj.dob, obj.image]
complete_field = [data for data in field_list if data is not None and data != '']
return len(complete_field)
class Meta(object):
"""Meta info"""
model = Junior
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',
'updated_at', 'notification_count', 'total_count', 'complete_field_count']

View File

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

View File

@ -3,22 +3,32 @@ 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
from guardian.utils import upload_image_to_alibaba
# Create your views here.
class UpdateJuniorProfile(viewsets.ViewSet):
"""Update junior profile"""
queryset = Junior.objects.all()
serializer_class = CreateJuniorSerializer
permission_classes = [IsAuthenticated]
def create(self, request, *args, **kwargs):
"""Use CreateJuniorSerializer"""
serializer = CreateJuniorSerializer(context={"user":request.user,
"first_name":request.data.get('first_name', ''),
"last_name": request.data.get('last_name',' ')},
data=request.data)
request_data = request.data
image = request.data.get('image')
image_url = ''
if image:
filename = f"images/{image.name}"
image_url = upload_image_to_alibaba(image, filename)
request_data = {"image": image_url}
serializer = CreateJuniorSerializer(context={"user":request.user, "image":image_url,
"first_name": request.data.get('first_name'),
"last_name": request.data.get('last_name')
},
data=request_data)
if serializer.is_valid():
"""save serializer"""
serializer.save()
@ -27,6 +37,7 @@ class UpdateJuniorProfile(viewsets.ViewSet):
class ValidateGuardianCode(viewsets.ViewSet):
"""Check guardian code exist or not"""
queryset = Guardian.objects.all()
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs):
@ -38,3 +49,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
queryset = Junior.objects.all()
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)

View File

@ -1,7 +1,9 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
"""Django import"""
"""Import OS module"""
import os
"""Import sys module"""
import sys
@ -18,6 +20,7 @@ def main():
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
"""execute command line function"""
execute_from_command_line(sys.argv)

View File

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

View File

@ -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,
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=50),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
}
# Database
@ -110,6 +112,30 @@ DATABASES = {
'PORT':os.getenv('DB_PORT'),
}
}
SWAGGER_SETTINGS = {
"exclude_namespaces": [],
"api_version": '0.1',
"api_path": "",
"enabled_methods": [
'get',
'post',
'put',
'patch',
'delete'
],
"api_key": '',
"is_authenticated": True,
"is_superuser": False,
'SECURITY_DEFINITIONS': {
"api_key": {
"type": "apiKey",
"name": "Authorization",
"in": "header",
},
},
}
# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
@ -172,33 +198,27 @@ CORS_ALLOW_HEADERS = (
https://docs.djangoproject.com/en/3.0/howto/static-files/"""
# EMAIL_BACKEND = os.getenv('EMAIL_BACKEND')
# EMAIL_HOST = os.getenv('EMAIL_HOST')
# EMAIL_PORT = os.getenv('EMAIL_PORT')
# EMAIL_USE_TLS = os.getenv('EMAIL_USE_TLS')
# EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER') # Replace with your Gmail email address
# EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD') # Replace with your Gmail email password or App password
# EMAIL_FROM_ADDRESS = os.getenv('EMAIL_FROM_ADDRESS')
GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID')
GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET')
EMAIL_BACKEND="django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST="smtp.sendgrid.net"
EMAIL_PORT="587"
EMAIL_USE_TLS="True"
EMAIL_HOST_USER="apikey" # Replace with your Gmail email address
EMAIL_HOST_USER="apikey"
EMAIL_HOST_PASSWORD="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"
EMAIL_FROM_ADDRESS="zodbank@yopmail.com"
EMAIL_FROM_ADDRESS="support@zodbank.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="LTAI5t7w1gq1CswJtvxtEZTd"
ALIYUN_OSS_ACCESS_KEY_SECRET="6yknAFpP2gVMhCWAJwbAjCEw2eehpf"
ALIYUN_OSS_BUCKET_NAME="zod-qa"
ALIYUN_OSS_ENDPOINT="oss-me-central-1.aliyuncs.com"
ALIYUN_OSS_REGION="Global"
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')
STATIC_URL = 'static/'
STATIC_ROOT = 'static'