conflict resolved

This commit is contained in:
abutalib-kiwi
2023-07-17 17:53:11 +05:30
25 changed files with 825 additions and 237 deletions

View File

@ -2,7 +2,7 @@
from django.contrib import admin from django.contrib import admin
"""Import django app""" """Import django app"""
from .models import UserEmailOtp, UserPhoneOtp, DefaultTaskImages, UserNotification, UserDelete from .models import UserEmailOtp, DefaultTaskImages, UserNotification, UserDelete, UserDeviceDetails
# Register your models here. # Register your models here.
@admin.register(UserDelete) @admin.register(UserDelete)
@ -19,6 +19,7 @@ class UserNotificationAdmin(admin.ModelAdmin):
list_display = ['user', 'push_notification', 'email_notification', 'sms_notification'] list_display = ['user', 'push_notification', 'email_notification', 'sms_notification']
def __str__(self): def __str__(self):
"""Return image url"""
return self.image_url return self.image_url
@admin.register(DefaultTaskImages) @admin.register(DefaultTaskImages)
class DefaultTaskImagesAdmin(admin.ModelAdmin): class DefaultTaskImagesAdmin(admin.ModelAdmin):
@ -26,6 +27,7 @@ class DefaultTaskImagesAdmin(admin.ModelAdmin):
list_display = ['task_name', 'image_url'] list_display = ['task_name', 'image_url']
def __str__(self): def __str__(self):
"""Return image url"""
return self.image_url return self.image_url
@admin.register(UserEmailOtp) @admin.register(UserEmailOtp)
@ -37,11 +39,11 @@ class UserEmailOtpAdmin(admin.ModelAdmin):
"""Return object in email and otp format""" """Return object in email and otp format"""
return self.email + '-' + self.otp return self.email + '-' + self.otp
@admin.register(UserPhoneOtp) @admin.register(UserDeviceDetails)
class UserPhoneOtpAdmin(admin.ModelAdmin): class UserDeviceDetailsAdmin(admin.ModelAdmin):
"""User Phone otp admin""" """User profile admin"""
list_display = ['phone'] list_display = ['user', 'device_id']
def __str__(self): def __str__(self):
"""Return object in phone number and otp format""" """Return user email"""
return self.phone + '-' + self.otp return self.user.email

View File

@ -0,0 +1,40 @@
"""middleware file"""
"""Django import"""
from rest_framework import status
from rest_framework.response import Response
from rest_framework.renderers import JSONRenderer
"""App django"""
from account.utils import custom_error_response
from account.models import UserDeviceDetails
from base.messages import ERROR_CODE, SUCCESS_CODE
# Custom middleware
# when user login with
# multiple device simultaneously
# It restricted login in
# multiple devices only
# user can login in single
# device at a time"""
class CustomMiddleware(object):
"""Custom middleware"""
def __init__(self, get_response):
"""response"""
self.get_response = get_response
def __call__(self, request):
# Code to be executed before the view is called
response = self.get_response(request)
# Code to be executed after the view is called
device_id = request.META.get('HTTP_DEVICE_ID')
if request.user.is_authenticated:
"""device details"""
device_details = UserDeviceDetails.objects.filter(user=request.user, device_id=device_id).last()
if device_id and not device_details:
custom_error = custom_error_response(ERROR_CODE['2037'], response_status=status.HTTP_404_NOT_FOUND)
response = Response(custom_error.data, status=status.HTTP_404_NOT_FOUND)
# Set content type header to "application/json"
response['Content-Type'] = 'application/json'
# Render the response as JSON
renderer = JSONRenderer()
response.content = renderer.render(response.data)
return response

View File

@ -0,0 +1,21 @@
# Generated by Django 4.2.2 on 2023-07-14 09:34
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('account', '0006_alter_useremailotp_options_and_more'),
]
operations = [
migrations.AlterModelOptions(
name='defaulttaskimages',
options={'verbose_name': 'Default Task images', 'verbose_name_plural': 'Default Task images'},
),
migrations.AlterModelOptions(
name='userdelete',
options={'verbose_name': 'Deleted User', 'verbose_name_plural': 'Deleted User'},
),
]

View File

@ -0,0 +1,31 @@
# Generated by Django 4.2.2 on 2023-07-14 11:08
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', '0007_alter_defaulttaskimages_options_and_more'),
]
operations = [
migrations.CreateModel(
name='UserDeviceDetails',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('device_id', models.CharField(max_length=500)),
('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_device_details', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'User Device Details',
'verbose_name_plural': 'User Device Details',
'db_table': 'user_device_details',
},
),
]

View File

@ -90,6 +90,8 @@ class DefaultTaskImages(models.Model):
class Meta(object): class Meta(object):
""" Meta information """ """ Meta information """
db_table = 'default_task_image' db_table = 'default_task_image'
verbose_name = 'Default Task images'
verbose_name_plural = 'Default Task images'
def __str__(self): def __str__(self):
"""return phone as an object""" """return phone as an object"""
@ -112,6 +114,8 @@ class UserDelete(models.Model):
class Meta(object): class Meta(object):
""" Meta information """ """ Meta information """
db_table = 'user_delete_information' db_table = 'user_delete_information'
verbose_name = 'Deleted User'
verbose_name_plural = 'Deleted User'
def __str__(self): def __str__(self):
return self.user.email return self.user.email
@ -141,3 +145,23 @@ class UserNotification(models.Model):
def __str__(self): def __str__(self):
return self.user.email return self.user.email
class UserDeviceDetails(models.Model):
"""
User notification details
"""
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_device_details')
"""Device ID"""
device_id = models.CharField(max_length=500)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta(object):
""" Meta information """
db_table = 'user_device_details'
verbose_name = 'User Device Details'
verbose_name_plural = 'User Device Details'
def __str__(self):
return self.user.email

View File

@ -1,17 +1,47 @@
"""Account serializer""" """Account serializer"""
"""Django Imoprt""" """Django Import"""
import random # Import Refresh token of jwt
from rest_framework import serializers from rest_framework import serializers
from django.contrib.auth.models import User from django.contrib.auth.models import User
from rest_framework_simplejwt.tokens import RefreshToken from rest_framework_simplejwt.tokens import RefreshToken
import secrets
"""App import""" """App import"""
# Import guardian's model,
# Import junior's model,
# Import account's model,
# Import constant from
# base package,
# Import messages from
# base package,
# Import some functions
# from utils file"""
from guardian.models import Guardian from guardian.models import Guardian
from junior.models import Junior from junior.models import Junior
from account.models import UserEmailOtp, DefaultTaskImages, UserDelete, UserNotification, UserPhoneOtp from account.models import UserEmailOtp, DefaultTaskImages, UserDelete, UserNotification, UserPhoneOtp
from base.constants import GUARDIAN, JUNIOR, SUPERUSER from base.constants import GUARDIAN, JUNIOR, SUPERUSER, NUMBER
from base.messages import ERROR_CODE_REQUIRED, ERROR_CODE, SUCCESS_CODE, STATUS_CODE_ERROR from base.messages import ERROR_CODE, SUCCESS_CODE, STATUS_CODE_ERROR
from .utils import delete_user_account_condition_social, delete_user_account_condition from .utils import delete_user_account_condition_social, delete_user_account_condition
# In this serializer file
# define google login serializer
# update junior profile,
# update guardian profile,
# super admin serializer,
# reset password,
# forgot password,
# change password,
# basic junior serializer,
# basic guardian serializer,
# user delete account serializer,
# user notification serializer,
# update user notification serializer,
# default task's images serializer,
# upload default task's images serializer,
# email verification serializer,
# phone otp serializer
class GoogleLoginSerializer(serializers.Serializer): class GoogleLoginSerializer(serializers.Serializer):
"""google login serializer""" """google login serializer"""
access_token = serializers.CharField(max_length=5000, required=True) access_token = serializers.CharField(max_length=5000, required=True)
@ -61,6 +91,7 @@ class ResetPasswordSerializer(serializers.Serializer):
def create(self, validated_data): def create(self, validated_data):
verification_code = validated_data.pop('verification_code') verification_code = validated_data.pop('verification_code')
password = validated_data.pop('password') password = validated_data.pop('password')
# fetch email otp object of the user
user_opt_details = UserEmailOtp.objects.filter(otp=verification_code, is_verified=True).last() user_opt_details = UserEmailOtp.objects.filter(otp=verification_code, is_verified=True).last()
if user_opt_details: if user_opt_details:
user_details = User.objects.filter(email=user_opt_details.email).last() user_details = User.objects.filter(email=user_opt_details.email).last()
@ -83,12 +114,14 @@ class ChangePasswordSerializer(serializers.Serializer):
def validate_current_password(self, value): def validate_current_password(self, value):
user = self.context user = self.context
# check old password
if self.context.password not in ('', None) and user.check_password(value): if self.context.password not in ('', None) and user.check_password(value):
return value return value
raise serializers.ValidationError(ERROR_CODE['2015']) raise serializers.ValidationError(ERROR_CODE['2015'])
def create(self, validated_data): def create(self, validated_data):
new_password = validated_data.pop('new_password') new_password = validated_data.pop('new_password')
current_password = validated_data.pop('current_password') current_password = validated_data.pop('current_password')
"""Check new password is different from current password"""
if new_password == current_password: if new_password == current_password:
raise serializers.ValidationError({"details": ERROR_CODE['2026']}) raise serializers.ValidationError({"details": ERROR_CODE['2026']})
user_details = User.objects.filter(email=self.context).last() user_details = User.objects.filter(email=self.context).last()
@ -107,15 +140,28 @@ class ForgotPasswordSerializer(serializers.Serializer):
class SuperUserSerializer(serializers.ModelSerializer): class SuperUserSerializer(serializers.ModelSerializer):
"""Super admin serializer""" """Super admin serializer"""
user_type = serializers.SerializerMethodField('get_user_type') user_type = serializers.SerializerMethodField('get_user_type')
auth_token = serializers.SerializerMethodField('get_auth_token')
refresh_token = serializers.SerializerMethodField('get_refresh_token')
def get_auth_token(self, obj):
refresh = RefreshToken.for_user(obj.auth)
access_token = str(refresh.access_token)
return access_token
def get_refresh_token(self, obj):
refresh = RefreshToken.for_user(obj.user)
refresh_token = str(refresh)
return refresh_token
def get_user_type(self, obj): def get_user_type(self, obj):
"""user type""" """user type"""
return SUPERUSER return str(NUMBER['three'])
class Meta(object): class Meta(object):
"""Meta info""" """Meta info"""
model = User model = User
fields = ['id', 'username', 'email', 'first_name', 'last_name', 'is_active', 'user_type'] fields = ['id', 'auth_token', 'refresh_token', 'username', 'email', 'first_name',
'last_name', 'is_active', 'user_type']
class GuardianSerializer(serializers.ModelSerializer): class GuardianSerializer(serializers.ModelSerializer):
@ -125,19 +171,24 @@ class GuardianSerializer(serializers.ModelSerializer):
first_name = serializers.SerializerMethodField('get_first_name') first_name = serializers.SerializerMethodField('get_first_name')
last_name = serializers.SerializerMethodField('get_last_name') last_name = serializers.SerializerMethodField('get_last_name')
auth_token = serializers.SerializerMethodField('get_auth_token') auth_token = serializers.SerializerMethodField('get_auth_token')
refresh_token = serializers.SerializerMethodField('get_refresh_token')
def get_auth_token(self, obj): def get_auth_token(self, obj):
refresh = RefreshToken.for_user(obj.user) refresh = RefreshToken.for_user(obj.user)
access_token = str(refresh.access_token) access_token = str(refresh.access_token)
return access_token return access_token
def get_refresh_token(self, obj):
refresh = RefreshToken.for_user(obj.user)
refresh_token = str(refresh)
return refresh_token
def get_user_type(self, obj): def get_user_type(self, obj):
"""user type""" """user type"""
email_verified = UserEmailOtp.objects.filter(email=obj.user.username).last() email_verified = UserEmailOtp.objects.filter(email=obj.user.username).last()
if email_verified and email_verified.user_type != None: if email_verified and email_verified.user_type is not None:
return email_verified.user_type return email_verified.user_type
return '2' return str(NUMBER['two'])
def get_auth(self, obj): def get_auth(self, obj):
"""user email address""" """user email address"""
@ -154,9 +205,9 @@ class GuardianSerializer(serializers.ModelSerializer):
class Meta(object): class Meta(object):
"""Meta info""" """Meta info"""
model = Guardian model = Guardian
fields = ['id', 'auth_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'family_name', fields = ['id', 'auth_token', 'refresh_token', 'email', 'first_name', 'last_name', 'country_code',
'gender', 'dob', 'referral_code', 'is_active', 'is_complete_profile', 'passcode', 'image', 'phone', 'family_name', 'gender', 'dob', 'referral_code', 'is_active',
'created_at', 'updated_at', 'user_type', 'country_name'] 'is_complete_profile', 'passcode', 'image', 'created_at', 'updated_at', 'user_type', 'country_name']
class JuniorSerializer(serializers.ModelSerializer): class JuniorSerializer(serializers.ModelSerializer):
@ -166,17 +217,23 @@ class JuniorSerializer(serializers.ModelSerializer):
first_name = serializers.SerializerMethodField('get_first_name') first_name = serializers.SerializerMethodField('get_first_name')
last_name = serializers.SerializerMethodField('get_last_name') last_name = serializers.SerializerMethodField('get_last_name')
auth_token = serializers.SerializerMethodField('get_auth_token') auth_token = serializers.SerializerMethodField('get_auth_token')
refresh_token = serializers.SerializerMethodField('get_refresh_token')
def get_auth_token(self, obj): def get_auth_token(self, obj):
refresh = RefreshToken.for_user(obj.auth) refresh = RefreshToken.for_user(obj.auth)
access_token = str(refresh.access_token) access_token = str(refresh.access_token)
return access_token return access_token
def get_refresh_token(self, obj):
refresh = RefreshToken.for_user(obj.user)
refresh_token = str(refresh)
return refresh_token
def get_user_type(self, obj): def get_user_type(self, obj):
email_verified = UserEmailOtp.objects.filter(email=obj.auth.username).last() email_verified = UserEmailOtp.objects.filter(email=obj.auth.username).last()
if email_verified and email_verified.user_type != None: if email_verified and email_verified.user_type is not None:
return email_verified.user_type return email_verified.user_type
return '1' return str(NUMBER['one'])
def get_auth(self, obj): def get_auth(self, obj):
return obj.auth.username return obj.auth.username
@ -190,9 +247,9 @@ class JuniorSerializer(serializers.ModelSerializer):
class Meta(object): class Meta(object):
"""Meta info""" """Meta info"""
model = Junior model = Junior
fields = ['id', 'auth_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob', fields = ['id', 'auth_token', 'refresh_token', 'email', 'first_name', 'last_name', 'country_code',
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image', 'phone', 'gender', 'dob', 'guardian_code', 'referral_code','is_active',
'updated_at', 'user_type', 'country_name','is_invited'] 'is_complete_profile', 'created_at', 'image', 'updated_at', 'user_type', 'country_name','is_invited']
class EmailVerificationSerializer(serializers.ModelSerializer): class EmailVerificationSerializer(serializers.ModelSerializer):
"""Email verification serializer""" """Email verification serializer"""
@ -210,6 +267,7 @@ class DefaultTaskImagesSerializer(serializers.ModelSerializer):
model = DefaultTaskImages model = DefaultTaskImages
fields = ['id', 'task_name', 'image_url'] fields = ['id', 'task_name', 'image_url']
def create(self, validated_data): def create(self, validated_data):
# create default task object
data = DefaultTaskImages.objects.create(**validated_data) data = DefaultTaskImages.objects.create(**validated_data)
return data return data
@ -232,10 +290,11 @@ class UserDeleteSerializer(serializers.ModelSerializer):
data = validated_data.get('reason') data = validated_data.get('reason')
passwd = self.context['password'] passwd = self.context['password']
signup_method = self.context['signup_method'] signup_method = self.context['signup_method']
random_num = random.randint(0, 10000) random_num = secrets.randbelow(10001)
user_tb = User.objects.filter(id=user.id).last() user_tb = User.objects.filter(id=user.id).last()
user_type_datas = UserEmailOtp.objects.filter(email=user.email).last() user_type_datas = UserEmailOtp.objects.filter(email=user.email).last()
if user_tb and user_tb.check_password(passwd) and signup_method == '1': # check password and sign up method
if user_tb and user_tb.check_password(passwd) and signup_method == str(NUMBER['one']):
user_type_data = user_type_datas.user_type user_type_data = user_type_datas.user_type
instance = delete_user_account_condition(user, user_type_data, user_type, user_tb, data, random_num) instance = delete_user_account_condition(user, user_type_data, user_type, user_tb, data, random_num)
return instance return instance
@ -264,6 +323,7 @@ class UpdateUserNotificationSerializer(serializers.ModelSerializer):
def create(self, validated_data): def create(self, validated_data):
instance = UserNotification.objects.filter(user=self.context).last() instance = UserNotification.objects.filter(user=self.context).last()
if instance: if instance:
# change notification status
instance.push_notification = validated_data.get('push_notification',instance.push_notification) instance.push_notification = validated_data.get('push_notification',instance.push_notification)
instance.email_notification = validated_data.get('email_notification', instance.email_notification) instance.email_notification = validated_data.get('email_notification', instance.email_notification)
instance.sms_notification = validated_data.get('sms_notification', instance.sms_notification) instance.sms_notification = validated_data.get('sms_notification', instance.sms_notification)

View File

@ -3,12 +3,32 @@
from django.urls import path, include from django.urls import path, include
"""Third party import""" """Third party import"""
from rest_framework import routers from rest_framework import routers
"""Import view functions""" # Import view functions
# UserLogin views,
# SendPhoneOtp views,
# UserPhoneVerification views,
# UserEmailVerification views,
# ReSendEmailOtp views,
# ForgotPasswordAPIView views,
# ResetPasswordAPIView views,
# ChangePasswordAPIView views,
# UpdateProfileImage views,
# GoogleLoginViewSet views,
# SigninWithApple views,
# ProfileAPIViewSet views,
# UploadImageAPIViewSet views,
# DefaultImageAPIViewSet views,
# DeleteUserProfileAPIViewSet views,
# UserNotificationAPIViewSet views,
# UpdateUserNotificationAPIViewSet views,
# SendSupportEmail views,
# LogoutAPIView views,
# AccessTokenAPIView views"""
from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVerification, ReSendEmailOtp, from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVerification, ReSendEmailOtp,
ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage, ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage,
GoogleLoginViewSet, SigninWithApple, ProfileAPIViewSet, UploadImageAPIViewSet, GoogleLoginViewSet, SigninWithApple, ProfileAPIViewSet, UploadImageAPIViewSet,
DefaultImageAPIViewSet, DeleteUserProfileAPIViewSet, UserNotificationAPIViewSet, DefaultImageAPIViewSet, DeleteUserProfileAPIViewSet, UserNotificationAPIViewSet,
UpdateUserNotificationAPIViewSet, SendSupportEmail, LogoutAPIView) UpdateUserNotificationAPIViewSet, SendSupportEmail, LogoutAPIView, AccessTokenAPIView)
"""Router""" """Router"""
router = routers.SimpleRouter() router = routers.SimpleRouter()
@ -45,5 +65,6 @@ urlpatterns = [
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'), path('api/v1/apple-login/', SigninWithApple.as_view(), name='signup_with_apple'),
path('api/v1/send-support-email/', SendSupportEmail.as_view(), name='send-support-email'), path('api/v1/send-support-email/', SendSupportEmail.as_view(), name='send-support-email'),
path('api/v1/logout/', LogoutAPIView.as_view(), name='logout') path('api/v1/logout/', LogoutAPIView.as_view(), name='logout'),
path('api/v1/generate-token/', AccessTokenAPIView.as_view(), name='generate-token')
] ]

View File

@ -10,14 +10,40 @@ import string
from datetime import datetime from datetime import datetime
from calendar import timegm from calendar import timegm
from uuid import uuid4 from uuid import uuid4
# Import secrets module for generating random number
import secrets import secrets
from rest_framework import serializers from rest_framework import serializers
# Django App Import
# Import models from junior App,
# Import models from guardian App,
# Import models from account App,
# Import messages from base package"""
from junior.models import Junior from junior.models import Junior
from guardian.models import Guardian from guardian.models import Guardian
from account.models import UserDelete from account.models import UserDelete
from base.messages import ERROR_CODE from base.messages import ERROR_CODE
# Define delete
# user account condition,
# Define delete
# user account
# condition for social
# login account,
# Update junior account,
# Update guardian account,
# Define custom email for otp verification,
# Define support email for user's query,
# Define custom success response,
# Define custom error response,
# Generate access token,
# refresh token by using jwt,
# Define function for generating
# guardian code, junior code,
# referral code,
# Define function for generating
# alphanumeric code
def delete_user_account_condition(user, user_type_data, user_type, user_tb, data, random_num): def delete_user_account_condition(user, user_type_data, user_type, user_tb, data, random_num):
"""delete user account""" """delete user account"""
if user_type == '1' and user_type_data == '1': if user_type == '1' and user_type_data == '1':
@ -28,10 +54,11 @@ def delete_user_account_condition(user, user_type_data, user_type, user_tb, data
raise serializers.ValidationError({"details": ERROR_CODE['2030'], "code": "400", "status": "failed"}) 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.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.username = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower()
user_tb.password = 'None'
d_email = user_tb.email d_email = user_tb.email
o_mail = user.email o_mail = user.email
# update user email with dummy email
user_tb.save() user_tb.save()
"""create object in user delete model"""
instance = UserDelete.objects.create(user=user_tb, d_email=d_email, old_email=o_mail, instance = UserDelete.objects.create(user=user_tb, d_email=d_email, old_email=o_mail,
is_active=True, reason=data) is_active=True, reason=data)
@ -47,10 +74,11 @@ def delete_user_account_condition_social(user, user_type,user_tb, data, random_n
raise serializers.ValidationError({"details": ERROR_CODE['2030'], "code": "400", "status": "failed"}) 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.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.username = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower()
user_tb.password = 'None'
dummy_email = user_tb.email dummy_email = user_tb.email
old_mail = user.email old_mail = user.email
# update user email with dummy email
user_tb.save() user_tb.save()
"""create object in user delete model"""
instance_data = UserDelete.objects.create(user=user_tb, d_email=dummy_email, old_email=old_mail, instance_data = UserDelete.objects.create(user=user_tb, d_email=dummy_email, old_email=old_mail,
is_active=True, reason=data) is_active=True, reason=data)
@ -59,6 +87,7 @@ def junior_account_update(user_tb):
"""junior account delete""" """junior account delete"""
junior_data = Junior.objects.filter(auth__email=user_tb.email).first() junior_data = Junior.objects.filter(auth__email=user_tb.email).first()
if junior_data: if junior_data:
# Update junior account
junior_data.is_active = False junior_data.is_active = False
junior_data.is_verified = False junior_data.is_verified = False
junior_data.guardian_code = '{}' junior_data.guardian_code = '{}'
@ -68,10 +97,12 @@ def guardian_account_update(user_tb):
"""update guardian account after delete the user account""" """update guardian account after delete the user account"""
guardian_data = Guardian.objects.filter(user__email=user_tb.email).first() guardian_data = Guardian.objects.filter(user__email=user_tb.email).first()
if guardian_data: if guardian_data:
# Update guardian account
guardian_data.is_active = False guardian_data.is_active = False
guardian_data.is_verified = False guardian_data.is_verified = False
guardian_data.save() guardian_data.save()
jun_data = Junior.objects.filter(guardian_code__icontains=str(guardian_data.guardian_code)) jun_data = Junior.objects.filter(guardian_code__icontains=str(guardian_data.guardian_code))
"""Disassociate relation between guardian and junior"""
for data in jun_data: for data in jun_data:
data.guardian_code.remove(guardian_data.guardian_code) data.guardian_code.remove(guardian_data.guardian_code)
data.save() data.save()
@ -79,6 +110,7 @@ def send_otp_email(recipient_email, otp):
"""Send otp on email with template""" """Send otp on email with template"""
from_email = settings.EMAIL_FROM_ADDRESS from_email = settings.EMAIL_FROM_ADDRESS
recipient_list = [recipient_email] recipient_list = [recipient_email]
"""Send otp on email"""
send_templated_mail( send_templated_mail(
template_name='email_otp_verification.email', template_name='email_otp_verification.email',
from_email=from_email, from_email=from_email,
@ -93,6 +125,7 @@ def send_support_email(name, sender, subject, message):
"""Send otp on email with template""" """Send otp on email with template"""
to_email = [settings.EMAIL_FROM_ADDRESS] to_email = [settings.EMAIL_FROM_ADDRESS]
from_email = settings.DEFAULT_ADDRESS from_email = settings.DEFAULT_ADDRESS
"""Send support email to zod bank support team"""
send_templated_mail( send_templated_mail(
template_name='support_mail.email', template_name='support_mail.email',
from_email=from_email, from_email=from_email,
@ -183,7 +216,15 @@ def get_token(data: dict = dict):
def generate_alphanumeric_code(length): def generate_alphanumeric_code(length):
"""Generate alphanumeric code"""
alphabet = string.ascii_letters + string.digits alphabet = string.ascii_letters + string.digits
code = ''.join(secrets.choice(alphabet) for _ in range(length)) code = ''.join(secrets.choice(alphabet) for _ in range(length))
return code return code
def generate_code(value, user_id):
"""generate referral, junior and guardian code"""
code = value + str(user_id).zfill(3)
return code

View File

@ -5,17 +5,23 @@ from rest_framework import viewsets, status, views
from rest_framework.decorators import action from rest_framework.decorators import action
import random import random
import logging import logging
from PIL import Image
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone from django.utils import timezone
import jwt import jwt
from django.contrib.auth import logout from django.contrib.auth import logout
"""App Import"""
from guardian.utils import upload_image_to_alibaba
from django.contrib.auth import authenticate, login from django.contrib.auth import authenticate, login
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
import requests
from rest_framework.response import Response
from django.conf import settings
"""App Import"""
from guardian.models import Guardian from guardian.models import Guardian
from junior.models import Junior from junior.models import Junior
from account.models import UserProfile, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification from guardian.utils import upload_image_to_alibaba
from account.models import UserDeviceDetails, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification
from django.contrib.auth.models import User from django.contrib.auth.models import User
"""Account serializer""" """Account serializer"""
from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer, from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer,
@ -25,22 +31,16 @@ from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSeriali
UserNotificationSerializer, UpdateUserNotificationSerializer, UserPhoneOtpSerializer) UserNotificationSerializer, UpdateUserNotificationSerializer, UserPhoneOtpSerializer)
from rest_framework_simplejwt.tokens import RefreshToken from rest_framework_simplejwt.tokens import RefreshToken
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import NUMBER from base.constants import NUMBER, ZOD, JUN, GRD
from guardian.tasks import generate_otp from guardian.tasks import generate_otp
from account.utils import send_otp_email, send_support_email, custom_response, custom_error_response from account.utils import (send_otp_email, send_support_email, custom_response, custom_error_response,
from rest_framework.permissions import IsAuthenticated generate_code)
from templated_email import send_templated_mail
import google.oauth2.credentials
import google.auth.transport.requests
from rest_framework import status
import requests
from rest_framework.response import Response
from django.conf import settings
from junior.serializers import JuniorProfileSerializer from junior.serializers import JuniorProfileSerializer
from guardian.serializers import GuardianProfileSerializer from guardian.serializers import GuardianProfileSerializer
class GoogleLoginMixin: class GoogleLoginMixin:
"""google login mixin""" """google login mixin"""
@staticmethod
def google_login(self, request): def google_login(self, request):
"""google login function""" """google login function"""
access_token = request.data.get('access_token') access_token = request.data.get('access_token')
@ -89,19 +89,15 @@ class GoogleLoginMixin:
if str(user_type) == '1': if str(user_type) == '1':
junior_query = Junior.objects.create(auth=user_obj, is_verified=True, is_active=True, junior_query = Junior.objects.create(auth=user_obj, is_verified=True, is_active=True,
image=profile_picture, signup_method='2', image=profile_picture, signup_method='2',
junior_code=''.join( junior_code=generate_code(JUN, user_obj.id),
[str(random.randrange(9)) for _ in range(6)]), referral_code=generate_code(ZOD, user_obj.id)
referral_code=''.join(
[str(random.randrange(9)) for _ in range(6)])
) )
serializer = JuniorSerializer(junior_query) serializer = JuniorSerializer(junior_query)
if str(user_type) == '2': if str(user_type) == '2':
guardian_query = Guardian.objects.create(user=user_obj, is_verified=True, is_active=True, guardian_query = Guardian.objects.create(user=user_obj, is_verified=True, is_active=True,
image=profile_picture,signup_method='2', image=profile_picture,signup_method='2',
guardian_code=''.join( guardian_code=generate_code(GRD, user_obj.id),
[str(random.randrange(9)) for _ in range(6)]), referral_code=generate_code(ZOD, user_obj.id)
referral_code=''.join(
[str(random.randrange(9)) for _ in range(6)])
) )
serializer = GuardianSerializer(guardian_query) serializer = GuardianSerializer(guardian_query)
# Return a JSON response with the user's email and name # Return a JSON response with the user's email and name
@ -143,18 +139,15 @@ class SigninWithApple(views.APIView):
user = User.objects.create(**user_data) user = User.objects.create(**user_data)
if str(user_type) == '1': if str(user_type) == '1':
junior_query = Junior.objects.create(auth=user, is_verified=True, is_active=True, junior_query = Junior.objects.create(auth=user, is_verified=True, is_active=True,
signup_method='3',junior_code=''.join( signup_method='3',
[str(random.randrange(9)) for _ in range(6)]), junior_code=generate_code(JUN, user.id),
referral_code=''.join( referral_code=generate_code(ZOD, user.id))
[str(random.randrange(9)) for _ in range(6)]))
serializer = JuniorSerializer(junior_query) serializer = JuniorSerializer(junior_query)
if str(user_type) == '2': if str(user_type) == '2':
guardian_query = Guardian.objects.create(user=user, is_verified=True, is_active=True, guardian_query = Guardian.objects.create(user=user, is_verified=True, is_active=True,
signup_method='3', signup_method='3',
guardian_code=''.join( guardian_code=generate_code(GRD, user.id),
[str(random.randrange(9)) for _ in range(6)]), referral_code=generate_code(ZOD, user.id))
referral_code=''.join(
[str(random.randrange(9)) for _ in range(6)]))
serializer = GuardianSerializer(guardian_query) serializer = GuardianSerializer(guardian_query)
return custom_response(SUCCESS_CODE['3003'], serializer.data, return custom_response(SUCCESS_CODE['3003'], serializer.data,
response_status=status.HTTP_200_OK) response_status=status.HTTP_200_OK)
@ -169,9 +162,7 @@ class UpdateProfileImage(views.APIView):
def put(self, request, format=None): def put(self, request, format=None):
try: try:
image = request.data['image'] image = request.data['image']
img = Image.open(image) if image and image.size == NUMBER['zero']:
width, height = img.size
if width == NUMBER['zero'] or height == NUMBER['zero']:
return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST)
filename = f"images/{image.name}" filename = f"images/{image.name}"
image_url = upload_image_to_alibaba(image, filename) image_url = upload_image_to_alibaba(image, filename)
@ -189,6 +180,7 @@ class UpdateProfileImage(views.APIView):
return custom_response(SUCCESS_CODE['3017'], serializer.data, response_status=status.HTTP_200_OK) 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) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
except Exception as e: except Exception as e:
logging.error(e)
return custom_error_response(ERROR_CODE['2036'],response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(ERROR_CODE['2036'],response_status=status.HTTP_400_BAD_REQUEST)
class ChangePasswordAPIView(views.APIView): class ChangePasswordAPIView(views.APIView):
@ -213,6 +205,7 @@ class ResetPasswordAPIView(views.APIView):
class ForgotPasswordAPIView(views.APIView): class ForgotPasswordAPIView(views.APIView):
"""Forgot password""" """Forgot password"""
def post(self, request): def post(self, request):
serializer = ForgotPasswordSerializer(data=request.data) serializer = ForgotPasswordSerializer(data=request.data)
if serializer.is_valid(): if serializer.is_valid():
@ -221,7 +214,7 @@ class ForgotPasswordAPIView(views.APIView):
User.objects.get(email=email) User.objects.get(email=email)
except User.DoesNotExist: except User.DoesNotExist:
return custom_error_response(ERROR_CODE['2004'], response_status=status.HTTP_404_NOT_FOUND) return custom_error_response(ERROR_CODE['2004'], response_status=status.HTTP_404_NOT_FOUND)
verification_code = ''.join([str(random.randrange(9)) for _ in range(6)]) verification_code = generate_otp()
# Send the verification code to the user's email # Send the verification code to the user's email
from_email = settings.EMAIL_FROM_ADDRESS from_email = settings.EMAIL_FROM_ADDRESS
recipient_list = [email] recipient_list = [email]
@ -233,7 +226,6 @@ class ForgotPasswordAPIView(views.APIView):
'verification_code': verification_code 'verification_code': verification_code
} }
) )
expiry = timezone.now() + timezone.timedelta(days=1) expiry = timezone.now() + timezone.timedelta(days=1)
user_data, created = UserEmailOtp.objects.get_or_create(email=email) user_data, created = UserEmailOtp.objects.get_or_create(email=email)
if created: if created:
@ -289,6 +281,7 @@ class UserLogin(viewsets.ViewSet):
def login(self, request): def login(self, request):
username = request.data.get('username') username = request.data.get('username')
password = request.data.get('password') password = request.data.get('password')
device_id = request.META.get('HTTP_DEVICE_ID')
user = authenticate(request, username=username, password=password) user = authenticate(request, username=username, password=password)
try: try:
@ -300,6 +293,10 @@ class UserLogin(viewsets.ViewSet):
junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last() junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last()
if junior_data: if junior_data:
serializer = JuniorSerializer(junior_data).data serializer = JuniorSerializer(junior_data).data
device_details, created = UserDeviceDetails.objects.get_or_create(user=user)
if device_details:
device_details.device_id = device_id
device_details.save()
return custom_response(SUCCESS_CODE['3003'], serializer, response_status=status.HTTP_200_OK) return custom_response(SUCCESS_CODE['3003'], serializer, response_status=status.HTTP_200_OK)
else: else:
return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED) return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED)
@ -308,7 +305,8 @@ class UserLogin(viewsets.ViewSet):
email_verified = UserEmailOtp.objects.filter(email=username).last() email_verified = UserEmailOtp.objects.filter(email=username).last()
refresh = RefreshToken.for_user(user) refresh = RefreshToken.for_user(user)
access_token = str(refresh.access_token) access_token = str(refresh.access_token)
data = {"auth_token":access_token, "is_profile_complete": False, refresh_token = str(refresh)
data = {"auth_token":access_token, "refresh_token":refresh_token, "is_profile_complete": False,
"user_type": email_verified.user_type, "user_type": email_verified.user_type,
} }
is_verified = False is_verified = False
@ -323,7 +321,7 @@ class UserLogin(viewsets.ViewSet):
return custom_response(ERROR_CODE['2024'], {"email_otp": otp, "is_email_verified": is_verified}, return custom_response(ERROR_CODE['2024'], {"email_otp": otp, "is_email_verified": is_verified},
response_status=status.HTTP_200_OK) response_status=status.HTTP_200_OK)
data.update({"is_email_verified": is_verified}) data.update({"is_email_verified": is_verified})
return custom_response(None, data, response_status=status.HTTP_200_OK) return custom_response(SUCCESS_CODE['3003'], data, response_status=status.HTTP_200_OK)
@action(methods=['post'], detail=False) @action(methods=['post'], detail=False)
def admin_login(self, request): def admin_login(self, request):
@ -342,7 +340,8 @@ class UserLogin(viewsets.ViewSet):
logging.error(e) logging.error(e)
refresh = RefreshToken.for_user(user) refresh = RefreshToken.for_user(user)
access_token = str(refresh.access_token) access_token = str(refresh.access_token)
data = {"auth_token": access_token, "user_role": '3'} refresh_token = str(refresh)
data = {"auth_token": access_token, "refresh_token":refresh_token, "user_type": '3'}
return custom_response(None, data, response_status=status.HTTP_200_OK) return custom_response(None, data, response_status=status.HTTP_200_OK)
class UserEmailVerification(viewsets.ModelViewSet): class UserEmailVerification(viewsets.ModelViewSet):
@ -379,7 +378,9 @@ class UserEmailVerification(viewsets.ModelViewSet):
guardian_data.save() guardian_data.save()
refresh = RefreshToken.for_user(user_obj) refresh = RefreshToken.for_user(user_obj)
access_token = str(refresh.access_token) access_token = str(refresh.access_token)
return custom_response(SUCCESS_CODE['3011'], {"auth_token":access_token}, refresh_token = str(refresh)
return custom_response(SUCCESS_CODE['3011'], {"auth_token":access_token,
"refresh_token":refresh_token},
response_status=status.HTTP_200_OK) response_status=status.HTTP_200_OK)
else: else:
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
@ -391,6 +392,8 @@ class ReSendEmailOtp(viewsets.ModelViewSet):
"""Send otp on phone""" """Send otp on phone"""
queryset = UserEmailOtp.objects.all() queryset = UserEmailOtp.objects.all()
serializer_class = EmailVerificationSerializer serializer_class = EmailVerificationSerializer
permission_classes = [IsAuthenticated]
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
otp = generate_otp() otp = generate_otp()
if User.objects.filter(email=request.data['email']): if User.objects.filter(email=request.data['email']):
@ -412,6 +415,8 @@ class ProfileAPIViewSet(viewsets.ModelViewSet):
"""Profile viewset""" """Profile viewset"""
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = JuniorProfileSerializer serializer_class = JuniorProfileSerializer
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
"""profile view""" """profile view"""
if str(self.request.GET.get('user_type')) == '1': if str(self.request.GET.get('user_type')) == '1':
@ -425,8 +430,6 @@ class ProfileAPIViewSet(viewsets.ModelViewSet):
serializer = GuardianProfileSerializer(guardian_data) serializer = GuardianProfileSerializer(guardian_data)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
class UploadImageAPIViewSet(viewsets.ModelViewSet): class UploadImageAPIViewSet(viewsets.ModelViewSet):
"""Profile viewset""" """Profile viewset"""
queryset = DefaultTaskImages.objects.all() queryset = DefaultTaskImages.objects.all()
@ -435,9 +438,7 @@ class UploadImageAPIViewSet(viewsets.ModelViewSet):
"""profile view""" """profile view"""
image_data = request.data['image_url'] image_data = request.data['image_url']
filename = f"default_task_images/{image_data.name}" filename = f"default_task_images/{image_data.name}"
img = Image.open(image_data) if image_data.size == NUMBER['zero']:
width, height = img.size
if width == NUMBER['zero'] or height == NUMBER['zero']:
return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST)
image = upload_image_to_alibaba(image_data, filename) image = upload_image_to_alibaba(image_data, filename)
image_data = image image_data = image
@ -452,6 +453,7 @@ class DefaultImageAPIViewSet(viewsets.ModelViewSet):
"""Profile viewset""" """Profile viewset"""
queryset = DefaultTaskImages.objects.all() queryset = DefaultTaskImages.objects.all()
serializer_class = DefaultTaskImagesDetailsSerializer serializer_class = DefaultTaskImagesDetailsSerializer
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
"""profile view""" """profile view"""
queryset = DefaultTaskImages.objects.all() queryset = DefaultTaskImages.objects.all()
@ -482,6 +484,7 @@ class UserNotificationAPIViewSet(viewsets.ModelViewSet):
"""notification viewset""" """notification viewset"""
queryset = UserNotification.objects.all() queryset = UserNotification.objects.all()
serializer_class = UserNotificationSerializer serializer_class = UserNotificationSerializer
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
"""profile view""" """profile view"""
queryset = self.queryset.filter(user=request.user) queryset = self.queryset.filter(user=request.user)
@ -493,6 +496,7 @@ class UpdateUserNotificationAPIViewSet(viewsets.ModelViewSet):
"""Update notification viewset""" """Update notification viewset"""
queryset = UserNotification.objects.all() queryset = UserNotification.objects.all()
serializer_class = UpdateUserNotificationSerializer serializer_class = UpdateUserNotificationSerializer
permission_classes = [IsAuthenticated]
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
"""profile view""" """profile view"""
@ -506,6 +510,8 @@ class UpdateUserNotificationAPIViewSet(viewsets.ModelViewSet):
class SendSupportEmail(views.APIView): class SendSupportEmail(views.APIView):
"""support email api""" """support email api"""
permission_classes = (IsAuthenticated,)
def post(self, request): def post(self, request):
name = request.data.get('name') name = request.data.get('name')
sender = request.data.get('email') sender = request.data.get('email')
@ -520,11 +526,26 @@ class SendSupportEmail(views.APIView):
else: else:
return custom_error_response(ERROR_CODE['2033'], response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(ERROR_CODE['2033'], response_status=status.HTTP_400_BAD_REQUEST)
class LogoutAPIView(views.APIView): class LogoutAPIView(views.APIView):
"""Log out API"""
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
def post(self, request): def post(self, request):
logout(request) logout(request)
request.session.flush() request.session.flush()
return custom_response(SUCCESS_CODE['3020'], response_status=status.HTTP_200_OK) return custom_response(SUCCESS_CODE['3020'], response_status=status.HTTP_200_OK)
class AccessTokenAPIView(views.APIView):
"""generate access token API"""
def post(self, request):
# Assuming you have a refresh_token string
refresh_token = request.data['refresh_token']
# Create a RefreshToken instance from the refresh token string
refresh = RefreshToken(refresh_token)
# Generate a new access token
access_token = str(refresh.access_token)
data = {"auth_token": access_token}
return custom_response(None, data, response_status=status.HTTP_200_OK)

View File

@ -6,52 +6,25 @@ import os
# GOOGLE_URL used for interact with google server to verify user existence. # GOOGLE_URL used for interact with google server to verify user existence.
#GOOGLE_URL = "https://www.googleapis.com/plus/v1/" #GOOGLE_URL = "https://www.googleapis.com/plus/v1/"
# Define Code prefix word
# for guardian code,
# junior code,
# referral code"""
ZOD = 'ZOD'
JUN = 'JUN'
GRD = 'GRD'
# Define number variable
# from zero to
# twenty and
# some standard
# number"""
NUMBER = { NUMBER = {
'point_zero': 0.0, 'point_zero': 0.0, 'zero': 0, 'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6, 'seven': 7,
'zero': 0, 'eight': 8, 'nine': 9, 'ten': 10, 'eleven': 11, 'twelve': 12, 'thirteen': 13, 'fourteen': 14, 'fifteen': 15,
'one': 1, 'sixteen': 16, 'seventeen': 17, 'eighteen': 18, 'nineteen': 19, 'twenty': 20,
'two': 2, 'twenty_one': 21, 'twenty_two': 22,'twenty_three': 23, 'twenty_four': 24, 'twenty_five': 25,
'three': 3, 'thirty': 30, 'forty': 40, 'fifty': 50, 'sixty': 60, 'seventy': 70, 'eighty': 80, 'ninty': 90,
'four': 4, 'ninety_nine': 99, 'hundred': 100,
'five': 5,
'six': 6,
'seven': 7,
'eight': 8,
'nine': 9,
'ten': 10,
'eleven': 11,
'twelve': 12,
'thirteen': 13,
'fourteen': 14,
'fifteen': 15,
'sixteen': 16,
'seventeen': 17,
'eighteen': 18,
'nineteen': 19,
'twenty_four': 24,
'twenty_one': 21,
'twenty_two': 22,
'twenty_five': 25,
'thirty': 30,
'thirty_five': 35,
'thirty_six': 36,
'forty': 40,
'fifty': 50,
'fifty_nine': 59,
'sixty': 60,
'seventy_five': 75,
'eighty': 80,
'ninty_five': 95,
'ninty_six': 96,
'ninety_nine': 99,
'hundred': 100,
'one_one_nine': 119,
'one_twenty': 120,
'four_zero_four': 404,
'five_hundred': 500,
'minus_one': -1,
'point_three': 0.3,
'point_seven': 0.7
} }
@ -71,10 +44,6 @@ FILE_SIZE = 5 * 1024 * 1024
# String constant for configurable date for allocation lock period # String constant for configurable date for allocation lock period
ALLOCATION_LOCK_DATE = 1 ALLOCATION_LOCK_DATE = 1
sort_dict = {
'1': 'name',
'2': '-name'
}
"""user type""" """user type"""
USER_TYPE = ( USER_TYPE = (
('1', 'junior'), ('1', 'junior'),
@ -86,7 +55,7 @@ GENDERS = (
('1', 'Male'), ('1', 'Male'),
('2', 'Female') ('2', 'Female')
) )
"""Task status""" # Task status"""
TASK_STATUS = ( TASK_STATUS = (
('1', 'pending'), ('1', 'pending'),
('2', 'in-progress'), ('2', 'in-progress'),
@ -94,17 +63,20 @@ TASK_STATUS = (
('4', 'requested'), ('4', 'requested'),
('5', 'completed') ('5', 'completed')
) )
"""sign up method""" # sign up method
SIGNUP_METHODS = ( SIGNUP_METHODS = (
('1', 'manual'), ('1', 'manual'),
('2', 'google'), ('2', 'google'),
('3', 'apple') ('3', 'apple')
) )
"""relationship""" # relationship
RELATIONSHIP = ( RELATIONSHIP = (
('1', 'parent'), ('1', 'parent'),
('2', 'legal_guardian') ('2', 'legal_guardian')
) )
"""
Define task status
in a number"""
PENDING = 1 PENDING = 1
IN_PROGRESS = 2 IN_PROGRESS = 2
REJECTED = 3 REJECTED = 3
@ -113,6 +85,7 @@ COMPLETED = 5
TASK_POINTS = 5 TASK_POINTS = 5
# duplicate name used defined in constant PROJECT_NAME # duplicate name used defined in constant PROJECT_NAME
PROJECT_NAME = 'Zod Bank' PROJECT_NAME = 'Zod Bank'
# define user type constant
GUARDIAN = 'guardian' GUARDIAN = 'guardian'
JUNIOR = 'junior' JUNIOR = 'junior'
SUPERUSER = 'superuser' SUPERUSER = 'superuser'

View File

@ -47,6 +47,7 @@ ERROR_CODE = {
"2021": "Already register", "2021": "Already register",
"2022": "Invalid Guardian code", "2022": "Invalid Guardian code",
"2023": "Invalid user", "2023": "Invalid user",
# email not verified
"2024": "Email not verified", "2024": "Email not verified",
"2025": "Invalid input. Expected a list of strings.", "2025": "Invalid input. Expected a list of strings.",
"2026": "New password should not same as old password", "2026": "New password should not same as old password",
@ -54,13 +55,19 @@ ERROR_CODE = {
"2028": "You are not authorized person to sign up on this platform", "2028": "You are not authorized person to sign up on this platform",
"2029": "Validity of otp verification is expired", "2029": "Validity of otp verification is expired",
"2030": "Use correct user type and token", "2030": "Use correct user type and token",
# invalid password
"2031": "Invalid password", "2031": "Invalid password",
"2032": "Failed to send email", "2032": "Failed to send email",
"2033": "Missing required fields", "2033": "Missing required fields",
"2034": "Junior is not associated", "2034": "Junior is not associated",
# image size
"2035": "Image should not be 0 kb", "2035": "Image should not be 0 kb",
"2036": "Choose valid user" "2036": "Choose valid user",
# log in multiple device msg
"2037": "You are already log in another device",
"2038": "Choose valid action for task"
} }
"""Success message code"""
SUCCESS_CODE = { SUCCESS_CODE = {
# Success code for password # Success code for password
"3001": "Sign up successfully", "3001": "Sign up successfully",
@ -93,9 +100,13 @@ SUCCESS_CODE = {
"3019": "Support Email sent successfully", "3019": "Support Email sent successfully",
"3020": "Logged out successfully.", "3020": "Logged out successfully.",
"3021": "Add junior successfully", "3021": "Add junior successfully",
"3022": "Remove junior successfully" "3022": "Remove junior successfully",
"3023": "Junior is approved successfully",
"3024": "Junior request is rejected successfully",
"3025": "Task is approved successfully",
"3026": "Task is rejected successfully",
} }
"""status code error"""
STATUS_CODE_ERROR = { STATUS_CODE_ERROR = {
# Status code for Invalid Input # Status code for Invalid Input
"4001": ["Invalid input."], "4001": ["Invalid input."],

View File

@ -0,0 +1,21 @@
# Generated by Django 4.2.2 on 2023-07-14 09:34
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('guardian', '0014_guardian_signup_method'),
]
operations = [
migrations.AlterModelOptions(
name='guardian',
options={'verbose_name': 'Guardian', 'verbose_name_plural': 'Guardian'},
),
migrations.AlterModelOptions(
name='juniortask',
options={'verbose_name': 'Junior Task', 'verbose_name_plural': 'Junior Task'},
),
]

View File

@ -4,9 +4,37 @@ from django.db import models
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
"""Import Django app""" """Import Django app"""
from base.constants import GENDERS, TASK_STATUS, PENDING, TASK_POINTS, SIGNUP_METHODS from base.constants import GENDERS, TASK_STATUS, PENDING, TASK_POINTS, SIGNUP_METHODS
"""import Junior model"""
from junior.models import Junior from junior.models import Junior
"""Add user model""" """Add user model"""
User = get_user_model() User = get_user_model()
# Create your models here.
# Define junior model with
# various fields like
# phone, country code,
# country name,
# gender,
# date of birth,
# profile image,
# signup method,
# guardian code,
# referral code,
# referral code that used by the guardian
# is invited guardian
# profile is active or not
# profile is complete or not
# passcode
# guardian is verified or not
"""Define junior task model"""
# define name of the Task
# task description
# points of the task
# default image of the task
# image uploaded by junior
# task status
# task approved or not
# Create your models here. # Create your models here.
class Guardian(models.Model): class Guardian(models.Model):
@ -15,23 +43,31 @@ class Guardian(models.Model):
"""Contact details""" """Contact details"""
country_code = models.IntegerField(blank=True, null=True) country_code = models.IntegerField(blank=True, null=True)
phone = models.CharField(max_length=31, null=True, blank=True, default=None) phone = models.CharField(max_length=31, null=True, blank=True, default=None)
"""country name of the guardian"""
country_name = models.CharField(max_length=100, null=True, blank=True, default=None) country_name = models.CharField(max_length=100, null=True, blank=True, default=None)
"""Image info""" """Image info"""
image = models.URLField(null=True, blank=True, default=None) image = models.URLField(null=True, blank=True, default=None)
"""Personal info""" """Personal info"""
family_name = models.CharField(max_length=50, null=True, blank=True, default=None) family_name = models.CharField(max_length=50, null=True, blank=True, default=None)
"""gender of the guardian"""
gender = models.CharField(choices=GENDERS, max_length=15, null=True, blank=True, default=None) gender = models.CharField(choices=GENDERS, max_length=15, null=True, blank=True, default=None)
"""date of birth of the guardian"""
dob = models.DateField(max_length=15, null=True, blank=True, default=None) dob = models.DateField(max_length=15, null=True, blank=True, default=None)
"""Profile activity""" """Profile activity"""
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
"""guardian is verified or not"""
is_verified = models.BooleanField(default=False) is_verified = models.BooleanField(default=False)
"""guardian profile is complete or not"""
is_complete_profile = models.BooleanField(default=False) is_complete_profile = models.BooleanField(default=False)
"""passcode of the guardian profile"""
passcode = models.IntegerField(null=True, blank=True, default=None) passcode = models.IntegerField(null=True, blank=True, default=None)
"""Sign up method""" """Sign up method"""
signup_method = models.CharField(max_length=31, choices=SIGNUP_METHODS, default='1') signup_method = models.CharField(max_length=31, choices=SIGNUP_METHODS, default='1')
"""Codes""" """Guardian Codes"""
guardian_code = models.CharField(max_length=10, null=True, blank=True, default=None) guardian_code = models.CharField(max_length=10, null=True, blank=True, default=None)
"""Referral code"""
referral_code = models.CharField(max_length=10, null=True, blank=True, default=None) referral_code = models.CharField(max_length=10, null=True, blank=True, default=None)
"""Referral code that is used by guardian while signup"""
referral_code_used = models.CharField(max_length=10, null=True, blank=True, default=None) referral_code_used = models.CharField(max_length=10, null=True, blank=True, default=None)
"""Profile created and updated time""" """Profile created and updated time"""
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
@ -40,7 +76,10 @@ class Guardian(models.Model):
class Meta(object): class Meta(object):
""" Meta class """ """ Meta class """
db_table = 'guardians' db_table = 'guardians'
"""verbose name of the model"""
verbose_name = 'Guardian' verbose_name = 'Guardian'
"""change another name"""
verbose_name_plural = 'Guardian'
def __str__(self): def __str__(self):
"""Return email id""" """Return email id"""
@ -51,19 +90,23 @@ class JuniorTask(models.Model):
guardian = models.ForeignKey(Guardian, on_delete=models.CASCADE, related_name='guardian', verbose_name='Guardian') guardian = models.ForeignKey(Guardian, on_delete=models.CASCADE, related_name='guardian', verbose_name='Guardian')
"""task details""" """task details"""
task_name = models.CharField(max_length=100) task_name = models.CharField(max_length=100)
"""task description"""
task_description = models.CharField(max_length=500) task_description = models.CharField(max_length=500)
"""points of the task""" """points of the task"""
points = models.IntegerField(default=TASK_POINTS) points = models.IntegerField(default=TASK_POINTS)
"""last date of the task"""
due_date = models.DateField(auto_now_add=False, null=True, blank=True) due_date = models.DateField(auto_now_add=False, null=True, blank=True)
"""Images of task""" """Images of task that is upload by guardian"""
default_image = models.URLField(null=True, blank=True, default=None) default_image = models.URLField(null=True, blank=True, default=None)
"""image that is uploaded by junior"""
image = models.URLField(null=True, blank=True, default=None) image = models.URLField(null=True, blank=True, default=None)
"""associated junior with the task""" """associated junior with the task"""
junior = models.ForeignKey(Junior, on_delete=models.CASCADE, related_name='junior', verbose_name='Junior') junior = models.ForeignKey(Junior, on_delete=models.CASCADE, related_name='junior', verbose_name='Junior')
"""task status""" """task status"""
task_status = models.CharField(choices=TASK_STATUS, max_length=15, default=PENDING) task_status = models.CharField(choices=TASK_STATUS, max_length=15, default=PENDING)
"""task stage""" """task is active or not"""
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
"""Task is approved or not"""
is_approved = models.BooleanField(default=False) is_approved = models.BooleanField(default=False)
"""Profile created and updated time""" """Profile created and updated time"""
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
@ -72,7 +115,9 @@ class JuniorTask(models.Model):
class Meta(object): class Meta(object):
""" Meta class """ """ Meta class """
db_table = 'junior_task' db_table = 'junior_task'
"""verbose name of the model"""
verbose_name = 'Junior Task' verbose_name = 'Junior Task'
verbose_name_plural = 'Junior Task'
def __str__(self): def __str__(self):
"""Return email id""" """Return email id"""

View File

@ -1,19 +1,41 @@
"""Serializer of Guardian""" """Serializer of Guardian"""
"""Third party Django app""" """Third party Django app"""
import logging import logging
import random
from rest_framework import serializers from rest_framework import serializers
# Import Refresh token of jwt
from rest_framework_simplejwt.tokens import RefreshToken from rest_framework_simplejwt.tokens import RefreshToken
from django.db import transaction from django.db import transaction
from django.contrib.auth.models import User from django.contrib.auth.models import User
"""Import Django app""" """Import Django app"""
# Import guardian's model,
# Import junior's model,
# Import account's model,
# Import constant from
# base package,
# Import messages from
# base package,
# Import some functions
# from utils file"""
from .models import Guardian, JuniorTask from .models import Guardian, JuniorTask
from account.models import UserProfile, UserEmailOtp, UserNotification from account.models import UserProfile, UserEmailOtp, UserNotification
from account.serializers import JuniorSerializer from account.utils import generate_code
from junior.serializers import JuniorDetailSerializer from junior.serializers import JuniorDetailSerializer
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import NUMBER from base.constants import NUMBER, JUN, ZOD, GRD
from junior.models import Junior, JuniorPoints from junior.models import Junior, JuniorPoints
# In this serializer file
# define user serializer,
# create guardian serializer,
# task serializer,
# guardian serializer,
# task details serializer,
# top junior serializer,
# guardian profile serializer,
# approve junior serializer,
# approve task serializer,
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
"""User serializer""" """User serializer"""
auth_token = serializers.SerializerMethodField('get_auth_token') auth_token = serializers.SerializerMethodField('get_auth_token')
@ -37,12 +59,14 @@ class UserSerializer(serializers.ModelSerializer):
"""Create user profile""" """Create user profile"""
user = User.objects.create_user(username=email, email=email, password=password) user = User.objects.create_user(username=email, email=email, password=password)
UserNotification.objects.create(user=user) UserNotification.objects.create(user=user)
if user_type == '1': if user_type == str(NUMBER['one']):
Junior.objects.create(auth=user, junior_code=''.join([str(random.randrange(9)) for _ in range(6)]), # create junior profile
referral_code=''.join([str(random.randrange(9)) for _ in range(6)])) Junior.objects.create(auth=user, junior_code=generate_code(JUN, user.id),
if user_type == '2': referral_code=generate_code(ZOD, user.id))
Guardian.objects.create(user=user, guardian_code=''.join([str(random.randrange(9)) for _ in range(6)]), if user_type == str(NUMBER['two']):
referral_code=''.join([str(random.randrange(9)) for _ in range(6)])) # create guardian profile
Guardian.objects.create(user=user, guardian_code=generate_code(GRD, user.id),
referral_code=generate_code(ZOD, user.id))
return user return user
except Exception as e: except Exception as e:
"""Error handling""" """Error handling"""
@ -55,6 +79,7 @@ class UserSerializer(serializers.ModelSerializer):
"code": 400, "status":"failed", "code": 400, "status":"failed",
}) })
# update guardian profile
class CreateGuardianSerializer(serializers.ModelSerializer): class CreateGuardianSerializer(serializers.ModelSerializer):
"""Create guardian serializer""" """Create guardian serializer"""
"""Basic info""" """Basic info"""
@ -64,9 +89,12 @@ class CreateGuardianSerializer(serializers.ModelSerializer):
"""Contact details""" """Contact details"""
phone = serializers.CharField(max_length=20, required=False) phone = serializers.CharField(max_length=20, required=False)
country_code = serializers.IntegerField(required=False) country_code = serializers.IntegerField(required=False)
# basic info
family_name = serializers.CharField(max_length=100, required=False) family_name = serializers.CharField(max_length=100, required=False)
dob = serializers.DateField(required=False) dob = serializers.DateField(required=False)
# code info
referral_code = serializers.CharField(max_length=100, required=False) referral_code = serializers.CharField(max_length=100, required=False)
# image info
image = serializers.URLField(required=False) image = serializers.URLField(required=False)
class Meta(object): class Meta(object):
@ -99,11 +127,7 @@ class CreateGuardianSerializer(serializers.ModelSerializer):
user.last_name = self.context.get('last_name') user.last_name = self.context.get('last_name')
user.save() user.save()
"""Create guardian data""" """Create guardian data"""
guardian, created = Guardian.objects.get_or_create(user=self.context['user']) guardian = Guardian.objects.filter(user=self.context['user']).last()
if created:
"""Create referral code and guardian code"""
guardian.referral_code = ''.join([str(random.randrange(9)) for _ in range(4)])
guardian.guardian_code = ''.join([str(random.randrange(9)) for _ in range(4)])
if guardian: if guardian:
"""update details according to the data get from request""" """update details according to the data get from request"""
guardian.gender = validated_data.get('gender',guardian.gender) guardian.gender = validated_data.get('gender',guardian.gender)
@ -143,6 +167,7 @@ class TaskSerializer(serializers.ModelSerializer):
def create(self, validated_data): def create(self, validated_data):
"""create default task image data""" """create default task image data"""
validated_data['guardian'] = Guardian.objects.filter(user=self.context['user']).last() validated_data['guardian'] = Guardian.objects.filter(user=self.context['user']).last()
# update image of the task
images = self.context['image'] images = self.context['image']
validated_data['default_image'] = images validated_data['default_image'] = images
instance = JuniorTask.objects.create(**validated_data) instance = JuniorTask.objects.create(**validated_data)
@ -230,6 +255,7 @@ class GuardianProfileSerializer(serializers.ModelSerializer):
"""total filled fields count""" """total filled fields count"""
total_field_list = [obj.user.first_name, obj.country_name, total_field_list = [obj.user.first_name, obj.country_name,
obj.gender, obj.dob, obj.image] obj.gender, obj.dob, obj.image]
# count total complete field
total_complete_field = [data for data in total_field_list if data != '' and data is not None] total_complete_field = [data for data in total_field_list if data != '' and data is not None]
return len(total_complete_field) return len(total_complete_field)
@ -244,3 +270,39 @@ class GuardianProfileSerializer(serializers.ModelSerializer):
'guardian_code', 'notification_count', 'total_count', 'complete_field_count', 'referral_code', 'guardian_code', 'notification_count', 'total_count', 'complete_field_count', 'referral_code',
'is_active', 'is_complete_profile', 'created_at', 'image', 'signup_method', 'is_active', 'is_complete_profile', 'created_at', 'image', 'signup_method',
'updated_at', 'passcode'] 'updated_at', 'passcode']
class ApproveJuniorSerializer(serializers.ModelSerializer):
"""approve junior serializer"""
class Meta(object):
"""Meta info"""
model = Junior
fields = ['id', 'guardian_code']
def create(self, validated_data):
"""update guardian code"""
instance = self.context['junior']
instance.guardian_code = [self.context['guardian_code']]
instance.save()
return instance
class ApproveTaskSerializer(serializers.ModelSerializer):
"""approve task serializer"""
class Meta(object):
"""Meta info"""
model = JuniorTask
fields = ['id', 'task_status', 'is_approved']
def create(self, validated_data):
"""update task status """
instance = self.context['task_instance']
if self.context['action'] == str(NUMBER['one']):
# approve the task
instance.task_status = str(NUMBER['five'])
instance.is_approved = True
else:
# reject the task
instance.task_status = str(NUMBER['three'])
instance.is_approved = False
instance.save()
return instance

View File

@ -1,6 +1,7 @@
"""task files""" """task files"""
"""Django import""" """Django import"""
import random import secrets
def generate_otp(): def generate_otp():
"""generate random otp""" """generate random otp"""
return ''.join([str(random.randrange(9)) for _ in range(6)]) digits = "0123456789"
return "".join(secrets.choice(digits) for _ in range(6))

View File

@ -2,29 +2,41 @@
"""Django import""" """Django import"""
from django.urls import path, include from django.urls import path, include
from .views import (SignupViewset, UpdateGuardianProfile, AllTaskListAPIView, CreateTaskAPIView, TaskListAPIView, from .views import (SignupViewset, UpdateGuardianProfile, AllTaskListAPIView, CreateTaskAPIView, TaskListAPIView,
SearchTaskListAPIView, TopJuniorListAPIView) SearchTaskListAPIView, TopJuniorListAPIView, ApproveJuniorAPIView, ApproveTaskAPIView)
"""Third party import""" """Third party import"""
from rest_framework import routers from rest_framework import routers
"""Define Router""" """Define Router"""
router = routers.SimpleRouter() router = routers.SimpleRouter()
"""API End points with router""" # API End points with router
# in this file
# we define various api end point
# that is covered in this guardian
# section API:- like
# sign-up, create guardian profile,
# create-task,
# all task list, top junior,
# filter-task"""
"""Sign up API""" """Sign up API"""
router.register('sign-up', SignupViewset, basename='sign-up') router.register('sign-up', SignupViewset, basename='sign-up')
"""Create guardian profile API""" # Create guardian profile API"""
router.register('create-guardian-profile', UpdateGuardianProfile, basename='update-guardian-profile') router.register('create-guardian-profile', UpdateGuardianProfile, basename='update-guardian-profile')
"""Create Task API""" # Create Task API"""
router.register('create-task', CreateTaskAPIView, basename='create-task') router.register('create-task', CreateTaskAPIView, basename='create-task')
"""All Task list API""" # All Task list API"""
router.register('all-task-list', AllTaskListAPIView, basename='all-task-list') router.register('all-task-list', AllTaskListAPIView, basename='all-task-list')
"""Task list bases on the status API""" # Task list bases on the status API"""
router.register('task-list', TaskListAPIView, basename='task-list') router.register('task-list', TaskListAPIView, basename='task-list')
"""Leaderboard API""" # Leaderboard API"""
router.register('top-junior', TopJuniorListAPIView, basename='top-junior') router.register('top-junior', TopJuniorListAPIView, basename='top-junior')
"""Search Task list on the bases of status, due date, and task title API""" # Search Task list on the bases of status, due date, and task title API"""
router.register('filter-task', SearchTaskListAPIView, basename='filter-task') router.register('filter-task', SearchTaskListAPIView, basename='filter-task')
"""Define Url pattern""" # Approve junior API"""
router.register('approve-junior', ApproveJuniorAPIView, basename='approve-junior')
# Approve junior API"""
router.register('approve-task', ApproveTaskAPIView, basename='approve-task')
# Define Url pattern"""
urlpatterns = [ urlpatterns = [
path('api/v1/', include(router.urls)), path('api/v1/', include(router.urls)),
] ]

View File

@ -6,6 +6,14 @@ from django.conf import settings
"""Import tempfile""" """Import tempfile"""
import tempfile import tempfile
# Define upload image on
# ali baba cloud
# firstly save image
# in temporary file
# then check bucket name
# then upload on ali baba
# bucket and reform the image url"""
def upload_image_to_alibaba(image, filename): def upload_image_to_alibaba(image, filename):
"""upload image on oss alibaba bucket""" """upload image on oss alibaba bucket"""
# Save the image object to a temporary file # Save the image object to a temporary file

View File

@ -5,14 +5,24 @@ from rest_framework import viewsets, status
from rest_framework.pagination import PageNumberPagination from rest_framework.pagination import PageNumberPagination
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.utils import timezone from django.utils import timezone
from PIL import Image
from datetime import datetime, timedelta
"""Import Django app""" """Import Django app"""
# Import guardian's model,
# Import junior's model,
# Import account's model,
# Import constant from
# base package,
# Import messages from
# base package,
# Import some functions
# from utils file
# Import account's serializer
# Import account's task
from .serializers import (UserSerializer, CreateGuardianSerializer, TaskSerializer, TaskDetailsSerializer, from .serializers import (UserSerializer, CreateGuardianSerializer, TaskSerializer, TaskDetailsSerializer,
TopJuniorSerializer) TopJuniorSerializer, ApproveJuniorSerializer, ApproveTaskSerializer)
from .models import Guardian, JuniorTask from .models import Guardian, JuniorTask
from junior.models import Junior, JuniorPoints from junior.models import Junior, JuniorPoints
from junior.serializers import JuniorDetailSerializer
from account.models import UserEmailOtp, UserNotification from account.models import UserEmailOtp, UserNotification
from .tasks import generate_otp from .tasks import generate_otp
from account.utils import send_otp_email from account.utils import send_otp_email
@ -20,7 +30,17 @@ from account.utils import custom_response, custom_error_response
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import NUMBER from base.constants import NUMBER
from .utils import upload_image_to_alibaba from .utils import upload_image_to_alibaba
from django.db.models import Sum
""" Define APIs """
# Define Signup API,
# update guardian profile,
# list of all task
# list of task according to the status of the task
# create task API
# search task by name of the task API
# top junior API,
# approve junior API
# approve task API
# Create your views here. # Create your views here.
class SignupViewset(viewsets.ModelViewSet): class SignupViewset(viewsets.ModelViewSet):
"""Signup view set""" """Signup view set"""
@ -35,6 +55,7 @@ class SignupViewset(viewsets.ModelViewSet):
"""Generate otp""" """Generate otp"""
otp = generate_otp() otp = generate_otp()
expiry = timezone.now() + timezone.timedelta(days=1) expiry = timezone.now() + timezone.timedelta(days=1)
# create user email otp object
UserEmailOtp.objects.create(email=request.data['email'], otp=otp, UserEmailOtp.objects.create(email=request.data['email'], otp=otp,
user_type=str(request.data['user_type']), expired_at=expiry) user_type=str(request.data['user_type']), expired_at=expiry)
"""Send email to the register user""" """Send email to the register user"""
@ -56,12 +77,11 @@ class UpdateGuardianProfile(viewsets.ViewSet):
data = request.data data = request.data
image = request.data.get('image') image = request.data.get('image')
image_url = '' image_url = ''
img = Image.open(image)
width, height = img.size
if width == NUMBER['zero'] or height == NUMBER['zero']:
return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST)
if image: if image:
if image and image.size == NUMBER['zero']:
return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST)
filename = f"images/{image.name}" filename = f"images/{image.name}"
# upload image on ali baba
image_url = upload_image_to_alibaba(image, filename) image_url = upload_image_to_alibaba(image, filename)
data = {"image":image_url} data = {"image":image_url}
serializer = CreateGuardianSerializer(context={"user":request.user, serializer = CreateGuardianSerializer(context={"user":request.user,
@ -85,6 +105,7 @@ class AllTaskListAPIView(viewsets.ModelViewSet):
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
"""Create guardian profile""" """Create guardian profile"""
queryset = JuniorTask.objects.filter(guardian__user=request.user) queryset = JuniorTask.objects.filter(guardian__user=request.user)
# use TaskDetailsSerializer serializer
serializer = TaskDetailsSerializer(queryset, many=True) serializer = TaskDetailsSerializer(queryset, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
@ -104,7 +125,9 @@ class TaskListAPIView(viewsets.ModelViewSet):
queryset = JuniorTask.objects.filter(guardian__user=request.user, queryset = JuniorTask.objects.filter(guardian__user=request.user,
task_status=status_value).order_by('due_date','created_at') task_status=status_value).order_by('due_date','created_at')
paginator = self.pagination_class() paginator = self.pagination_class()
# use Pagination
paginated_queryset = paginator.paginate_queryset(queryset, request) paginated_queryset = paginator.paginate_queryset(queryset, request)
# use TaskDetailsSerializer serializer
serializer = TaskDetailsSerializer(paginated_queryset, many=True) serializer = TaskDetailsSerializer(paginated_queryset, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
@ -120,15 +143,15 @@ class CreateTaskAPIView(viewsets.ModelViewSet):
image_data = image image_data = image
else: else:
filename = f"images/{image}" filename = f"images/{image}"
img = Image.open(image) if image and image.size == NUMBER['zero']:
width, height = img.size
if width == NUMBER['zero'] or height == NUMBER['zero']:
return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST)
image_url = upload_image_to_alibaba(image, filename) image_url = upload_image_to_alibaba(image, filename)
image_data = image_url image_data = image_url
data.pop('default_image') data.pop('default_image')
# use TaskSerializer serializer
serializer = TaskSerializer(context={"user":request.user, "image":image_data}, data=data) serializer = TaskSerializer(context={"user":request.user, "image":image_data}, data=data)
if serializer.is_valid(): if serializer.is_valid():
# save serializer
serializer.save() serializer.save()
return custom_response(SUCCESS_CODE['3018'], serializer.data, response_status=status.HTTP_200_OK) return custom_response(SUCCESS_CODE['3018'], serializer.data, response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
@ -143,6 +166,7 @@ class SearchTaskListAPIView(viewsets.ModelViewSet):
def get_queryset(self): def get_queryset(self):
"""Get the queryset for the view""" """Get the queryset for the view"""
title = self.request.GET.get('title') title = self.request.GET.get('title')
# fetch junior query
junior_queryset = JuniorTask.objects.filter(guardian__user=self.request.user, task_name__icontains=title)\ junior_queryset = JuniorTask.objects.filter(guardian__user=self.request.user, task_name__icontains=title)\
.order_by('due_date', 'created_at') .order_by('due_date', 'created_at')
return junior_queryset return junior_queryset
@ -152,8 +176,9 @@ class SearchTaskListAPIView(viewsets.ModelViewSet):
queryset = self.get_queryset() queryset = self.get_queryset()
paginator = self.pagination_class() paginator = self.pagination_class()
# use pagination
paginated_queryset = paginator.paginate_queryset(queryset, request) paginated_queryset = paginator.paginate_queryset(queryset, request)
# use TaskSerializer serializer
serializer = TaskDetailsSerializer(paginated_queryset, many=True) serializer = TaskDetailsSerializer(paginated_queryset, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
@ -182,3 +207,64 @@ class TopJuniorListAPIView(viewsets.ModelViewSet):
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
class ApproveJuniorAPIView(viewsets.ViewSet):
"""approve junior by guardian"""
serializer_class = ApproveJuniorSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
"""Get the queryset for the view"""
guardian = Guardian.objects.filter(user__email=self.request.user).last()
# fetch junior query
junior_queryset = Junior.objects.filter(id=self.request.data.get('junior_id')).last()
return guardian, junior_queryset
def create(self, request, *args, **kwargs):
""" junior list"""
queryset = self.get_queryset()
# action 1 is use for approve and 2 for reject
if request.data['action'] == '1':
# use ApproveJuniorSerializer serializer
serializer = ApproveJuniorSerializer(context={"guardian_code": queryset[0].guardian_code,
"junior": queryset[1], "action": request.data['action']},
data=request.data)
if serializer.is_valid():
# save serializer
serializer.save()
return custom_response(SUCCESS_CODE['3023'], serializer.data, response_status=status.HTTP_200_OK)
else:
return custom_response(SUCCESS_CODE['3024'], response_status=status.HTTP_200_OK)
class ApproveTaskAPIView(viewsets.ViewSet):
"""approve junior by guardian"""
serializer_class = ApproveTaskSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
"""Get the queryset for the view"""
guardian = Guardian.objects.filter(user__email=self.request.user).last()
# task query
task_queryset = JuniorTask.objects.filter(id=self.request.data.get('task_id'),
guardian=guardian,
junior=self.request.data.get('junior_id')).last()
return guardian, task_queryset
def create(self, request, *args, **kwargs):
""" junior list"""
# action 1 is use for approve and 2 for reject
queryset = self.get_queryset()
# use ApproveJuniorSerializer serializer
serializer = ApproveTaskSerializer(context={"guardian_code": queryset[0].guardian_code,
"task_instance": queryset[1],
"action": str(request.data['action'])},
data=request.data)
if str(request.data['action']) == str(NUMBER['one']) and serializer.is_valid():
# save serializer
serializer.save()
return custom_response(SUCCESS_CODE['3025'], response_status=status.HTTP_200_OK)
elif str(request.data['action']) == str(NUMBER['two']) and serializer.is_valid():
# save serializer
serializer.save()
return custom_response(SUCCESS_CODE['3026'], response_status=status.HTTP_200_OK)
else:
return custom_response(ERROR_CODE['2038'], response_status=status.HTTP_400_BAD_REQUEST)

View File

@ -0,0 +1,21 @@
# Generated by Django 4.2.2 on 2023-07-14 09:34
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('junior', '0012_junior_is_invited'),
]
operations = [
migrations.AlterModelOptions(
name='junior',
options={'verbose_name': 'Junior', 'verbose_name_plural': 'Junior'},
),
migrations.AlterModelOptions(
name='juniorpoints',
options={'verbose_name': 'Junior Task Points', 'verbose_name_plural': 'Junior Task Points'},
),
]

View File

@ -1,42 +1,75 @@
"""Junior model """ """Junior model """
"""Import django""" """Import django"""
from django.db import models from django.db import models
"""Import get_user_model function"""
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
"""Import ArrayField"""
from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.fields import ArrayField
"""Import django app""" """Import django app"""
from base.constants import GENDERS, SIGNUP_METHODS, RELATIONSHIP from base.constants import GENDERS, SIGNUP_METHODS, RELATIONSHIP
"""Define User model"""
User = get_user_model() User = get_user_model()
# Create your models here. # Create your models here.
# Define junior model with
# various fields like
# phone, country code,
# country name,
# gender,
# date of birth,
# profile image,
# relationship type of the guardian
# signup method,
# guardian code,
# junior code,
# referral code,
# referral code that used by the junior
# is invited junior
# profile is active or not
# profile is complete or not
# passcode
# junior is verified or not
"""Define junior points model"""
# points of the junior
# position of the junior
class Junior(models.Model): class Junior(models.Model):
"""Junior model""" """Junior model"""
auth = models.ForeignKey(User, on_delete=models.CASCADE, related_name='junior_profile', verbose_name='Email') auth = models.ForeignKey(User, on_delete=models.CASCADE, related_name='junior_profile', verbose_name='Email')
"""Contact details""" # Contact details"""
phone = models.CharField(max_length=31, null=True, blank=True, default=None) phone = models.CharField(max_length=31, null=True, blank=True, default=None)
country_code = models.IntegerField(blank=True, null=True) country_code = models.IntegerField(blank=True, null=True)
# country name of the guardian"""
country_name = models.CharField(max_length=100, null=True, blank=True, default=None) country_name = models.CharField(max_length=100, null=True, blank=True, default=None)
"""Personal info""" # Personal info"""
gender = models.CharField(max_length=10, choices=GENDERS, null=True, blank=True, default=None) gender = models.CharField(max_length=10, choices=GENDERS, null=True, blank=True, default=None)
# Date of birth"""
dob = models.DateField(max_length=15, null=True, blank=True, default=None) dob = models.DateField(max_length=15, null=True, blank=True, default=None)
# Image of the junior"""
image = models.URLField(null=True, blank=True, default=None) image = models.URLField(null=True, blank=True, default=None)
"""relationship""" # relationship"""
relationship = models.CharField(max_length=31, choices=RELATIONSHIP, null=True, blank=True, relationship = models.CharField(max_length=31, choices=RELATIONSHIP, null=True, blank=True,
default='1') default='1')
"""Sign up method""" # Sign up method"""
signup_method = models.CharField(max_length=31, choices=SIGNUP_METHODS, default='1') signup_method = models.CharField(max_length=31, choices=SIGNUP_METHODS, default='1')
"""Codes""" # Codes"""
junior_code = models.CharField(max_length=10, null=True, blank=True, default=None) junior_code = models.CharField(max_length=10, null=True, blank=True, default=None)
# Guardian Codes"""
guardian_code = ArrayField(models.CharField(max_length=10, null=True, blank=True, default=None),null=True) guardian_code = ArrayField(models.CharField(max_length=10, null=True, blank=True, default=None),null=True)
# Referral code"""
referral_code = models.CharField(max_length=10, null=True, blank=True, default=None) referral_code = models.CharField(max_length=10, null=True, blank=True, default=None)
# Referral code that is used by junior while signup"""
referral_code_used = models.CharField(max_length=10, null=True, blank=True, default=None) referral_code_used = models.CharField(max_length=10, null=True, blank=True, default=None)
"""invited junior""" # invited junior"""
is_invited = models.BooleanField(default=False) is_invited = models.BooleanField(default=False)
"""Profile activity""" # Profile activity"""
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
# junior profile is complete or not"""
is_complete_profile = models.BooleanField(default=False) is_complete_profile = models.BooleanField(default=False)
# passcode of the junior profile"""
passcode = models.IntegerField(null=True, blank=True, default=None) passcode = models.IntegerField(null=True, blank=True, default=None)
# junior is verified or not"""
is_verified = models.BooleanField(default=False) is_verified = models.BooleanField(default=False)
"""Profile created and updated time""" # Profile created and updated time"""
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
@ -44,6 +77,8 @@ class Junior(models.Model):
""" Meta class """ """ Meta class """
db_table = 'junior' db_table = 'junior'
verbose_name = 'Junior' verbose_name = 'Junior'
# another name of the model"""
verbose_name_plural = 'Junior'
def __str__(self): def __str__(self):
"""Return email id""" """Return email id"""
@ -52,11 +87,11 @@ class Junior(models.Model):
class JuniorPoints(models.Model): class JuniorPoints(models.Model):
"""Junior model""" """Junior model"""
junior = models.OneToOneField(Junior, on_delete=models.CASCADE, related_name='junior_points') junior = models.OneToOneField(Junior, on_delete=models.CASCADE, related_name='junior_points')
"""Contact details""" # Contact details"""
total_task_points = models.IntegerField(blank=True, null=True, default=0) total_task_points = models.IntegerField(blank=True, null=True, default=0)
"""position of the junior""" # position of the junior"""
position = models.IntegerField(blank=True, null=True, default=99999) position = models.IntegerField(blank=True, null=True, default=99999)
"""Profile created and updated time""" # Profile created and updated time"""
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
@ -64,6 +99,8 @@ class JuniorPoints(models.Model):
""" Meta class """ """ Meta class """
db_table = 'junior_task_points' db_table = 'junior_task_points'
verbose_name = 'Junior Task Points' verbose_name = 'Junior Task Points'
# another name of the model"""
verbose_name_plural = 'Junior Task Points'
def __str__(self): def __str__(self):
"""Return email id""" """Return email id"""

View File

@ -8,11 +8,11 @@ from django.utils import timezone
from rest_framework_simplejwt.tokens import RefreshToken from rest_framework_simplejwt.tokens import RefreshToken
"""Import django app""" """Import django app"""
from account.utils import send_otp_email from account.utils import send_otp_email, generate_code
from junior.models import Junior, JuniorPoints from junior.models import Junior, JuniorPoints
from guardian.tasks import generate_otp from guardian.tasks import generate_otp
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER, JUN, ZOD
from guardian.models import Guardian, JuniorTask from guardian.models import Guardian, JuniorTask
from account.models import UserEmailOtp from account.models import UserEmailOtp
from junior.utils import junior_notification_email, junior_approval_mail from junior.utils import junior_notification_email, junior_approval_mail
@ -76,11 +76,7 @@ class CreateJuniorSerializer(serializers.ModelSerializer):
user.last_name = self.context.get('last_name') user.last_name = self.context.get('last_name')
user.save() user.save()
"""Create junior data""" """Create junior data"""
junior, created = Junior.objects.get_or_create(auth=self.context['user']) junior = Junior.objects.filter(auth=self.context['user']).last()
if created:
"""Create referral code and junior code"""
junior.referral_code = ''.join([str(random.randrange(9)) for _ in range(4)])
junior.junior_code = ''.join([str(random.randrange(9)) for _ in range(4)])
if junior: if junior:
"""update details according to the data get from request""" """update details according to the data get from request"""
junior.gender = validated_data.get('gender',junior.gender) junior.gender = validated_data.get('gender',junior.gender)
@ -134,8 +130,8 @@ class JuniorDetailSerializer(serializers.ModelSerializer):
"""Meta info""" """Meta info"""
model = Junior model = Junior
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob', fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
'guardian_code', 'is_invited', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image', 'guardian_code', 'is_invited', 'referral_code','is_active', 'is_complete_profile', 'created_at',
'updated_at'] 'image', 'updated_at']
class JuniorDetailListSerializer(serializers.ModelSerializer): class JuniorDetailListSerializer(serializers.ModelSerializer):
"""junior serializer""" """junior serializer"""
@ -279,8 +275,8 @@ class AddJuniorSerializer(serializers.ModelSerializer):
junior_data = Junior.objects.create(auth=user_data, gender=validated_data.get('gender'), junior_data = Junior.objects.create(auth=user_data, gender=validated_data.get('gender'),
dob=validated_data.get('dob'), is_invited=True, dob=validated_data.get('dob'), is_invited=True,
relationship=validated_data.get('relationship'), relationship=validated_data.get('relationship'),
junior_code=''.join([str(random.randrange(9)) for _ in range(4)]), junior_code=generate_code(JUN, user_data.id),
referral_code=''.join([str(random.randrange(9)) for _ in range(4)]), referral_code=generate_code(ZOD, user_data.id),
referral_code_used=guardian_data.referral_code) referral_code_used=guardian_data.referral_code)
"""Generate otp""" """Generate otp"""
otp_value = generate_otp() otp_value = generate_otp()

View File

@ -8,21 +8,29 @@ from rest_framework import routers
"""Router""" """Router"""
router = routers.SimpleRouter() router = routers.SimpleRouter()
# API End points with router
# in this file
# we define various api end point
# that is covered in this guardian
# section API:- like
# Create junior profile API, validate junior profile,
# junior list,
# add junior list, invited junior,
# filter-junior,
# remove junior"""
"""API End points with router""" """API End points with router"""
"""Create junior profile API"""
router.register('create-junior-profile', UpdateJuniorProfile, basename='profile-update') router.register('create-junior-profile', UpdateJuniorProfile, basename='profile-update')
"""validate guardian code API""" # validate guardian code API"""
router.register('validate-guardian-code', ValidateGuardianCode, basename='validate-guardian-code') router.register('validate-guardian-code', ValidateGuardianCode, basename='validate-guardian-code')
"""junior list API""" # junior list API"""
router.register('junior-list', JuniorListAPIView, basename='junior-list') router.register('junior-list', JuniorListAPIView, basename='junior-list')
"""Add junior list API""" # Add junior list API"""
router.register('add-junior', AddJuniorAPIView, basename='add-junior') router.register('add-junior', AddJuniorAPIView, basename='add-junior')
"""Invited junior list API""" # Invited junior list API"""
router.register('invited-junior', InvitedJuniorAPIView, basename='invited-junior') router.register('invited-junior', InvitedJuniorAPIView, basename='invited-junior')
"""Filter junior list API""" # Filter junior list API"""
router.register('filter-junior', FilterJuniorAPIView, basename='filter-junior') router.register('filter-junior', FilterJuniorAPIView, basename='filter-junior')
"""Define url pattern""" # Define url pattern"""
urlpatterns = [ urlpatterns = [
path('api/v1/', include(router.urls)), path('api/v1/', include(router.urls)),
path('api/v1/remove-junior/', RemoveJuniorAPIView.as_view()) path('api/v1/remove-junior/', RemoveJuniorAPIView.as_view())

View File

@ -1,28 +1,23 @@
"""Account utils""" """Account utils"""
"""Import django""" """Import django"""
from django.conf import settings from django.conf import settings
from rest_framework import viewsets, status
from rest_framework.response import Response
"""Third party Django app""" """Third party Django app"""
from templated_email import send_templated_mail from templated_email import send_templated_mail
import jwt
import string
from datetime import datetime
from calendar import timegm
from uuid import uuid4
import secrets
from rest_framework import serializers
from junior.models import Junior
from guardian.models import Guardian
from account.models import UserDelete
from base.messages import ERROR_CODE
# junior notification
# email for sending email
# when guardian create junior profile
# guardian get email when junior send
# request for approving the profile and
# being part of the zod bank and access the platform
# define junior notification email
# junior approval email
def junior_notification_email(recipient_email, full_name, email, password): def junior_notification_email(recipient_email, full_name, email, password):
"""Notification email""" """Notification email"""
from_email = settings.EMAIL_FROM_ADDRESS from_email = settings.EMAIL_FROM_ADDRESS
# recipient email"""
recipient_list = [recipient_email] recipient_list = [recipient_email]
# use send template mail for sending email"""
send_templated_mail( send_templated_mail(
template_name='junior_notification_email.email', template_name='junior_notification_email.email',
from_email=from_email, from_email=from_email,
@ -40,6 +35,7 @@ def junior_approval_mail(guardian, full_name):
"""junior approval mail""" """junior approval mail"""
from_email = settings.EMAIL_FROM_ADDRESS from_email = settings.EMAIL_FROM_ADDRESS
recipient_list = [guardian] recipient_list = [guardian]
# use send template mail for sending email"""
send_templated_mail( send_templated_mail(
template_name='junior_approval_mail.email', template_name='junior_approval_mail.email',
from_email=from_email, from_email=from_email,

View File

@ -2,9 +2,19 @@
from rest_framework import viewsets, status, generics,views from rest_framework import viewsets, status, generics,views
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.pagination import PageNumberPagination from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from PIL import Image
"""Django app import""" """Django app import"""
# Import guardian's model,
# Import junior's model,
# Import account's model,
# Import constant from
# base package,
# Import messages from
# base package,
# Import some functions
# from utils file
# Import account's serializer
# Import account's task
from junior.models import Junior from junior.models import Junior
from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer,\ from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer,\
RemoveJuniorSerializer) RemoveJuniorSerializer)
@ -13,6 +23,17 @@ from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import NUMBER from base.constants import NUMBER
from account.utils import custom_response, custom_error_response from account.utils import custom_response, custom_error_response
from guardian.utils import upload_image_to_alibaba from guardian.utils import upload_image_to_alibaba
""" Define APIs """
# Define validate guardian code API,
# update junior profile,
# list of all assosicated junior
# Add junior API
# invite junior API
# search junior API
# remove junior API,
# approve junior API
# Create your views here. # Create your views here.
class UpdateJuniorProfile(viewsets.ViewSet): class UpdateJuniorProfile(viewsets.ViewSet):
"""Update junior profile""" """Update junior profile"""
@ -25,12 +46,11 @@ class UpdateJuniorProfile(viewsets.ViewSet):
request_data = request.data request_data = request.data
image = request.data.get('image') image = request.data.get('image')
image_url = '' image_url = ''
img = Image.open(image)
width, height = img.size
if width == NUMBER['zero'] or height == NUMBER['zero']:
return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST)
if image: if image:
if image.size == NUMBER['zero']:
return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST)
filename = f"images/{image.name}" filename = f"images/{image.name}"
# upload image on ali baba
image_url = upload_image_to_alibaba(image, filename) image_url = upload_image_to_alibaba(image, filename)
request_data = {"image": image_url} request_data = {"image": image_url}
serializer = CreateJuniorSerializer(context={"user":request.user, "image":image_url, serializer = CreateJuniorSerializer(context={"user":request.user, "image":image_url,
@ -53,6 +73,7 @@ class ValidateGuardianCode(viewsets.ViewSet):
"""check guardian code""" """check guardian code"""
guardian_code = self.request.GET.get('guardian_code').split(',') guardian_code = self.request.GET.get('guardian_code').split(',')
for code in guardian_code: for code in guardian_code:
# fetch guardian object
guardian_data = Guardian.objects.filter(guardian_code=code).exists() guardian_data = Guardian.objects.filter(guardian_code=code).exists()
if guardian_data: if guardian_data:
return custom_response(SUCCESS_CODE['3013'], response_status=status.HTTP_200_OK) return custom_response(SUCCESS_CODE['3013'], response_status=status.HTTP_200_OK)
@ -64,10 +85,13 @@ class JuniorListAPIView(viewsets.ModelViewSet):
serializer_class = JuniorDetailListSerializer serializer_class = JuniorDetailListSerializer
queryset = Junior.objects.all() queryset = Junior.objects.all()
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
""" junior list""" """ junior list"""
guardian_data = Guardian.objects.filter(user__email=request.user).last() guardian_data = Guardian.objects.filter(user__email=request.user).last()
queryset = Junior.objects.filter(guardian_code__icontains=str(guardian_data.guardian_code)) queryset = Junior.objects.filter(guardian_code__icontains=str(guardian_data.guardian_code))
# use JuniorDetailListSerializer serializer
serializer = JuniorDetailListSerializer(queryset, many=True) serializer = JuniorDetailListSerializer(queryset, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
@ -80,8 +104,10 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
""" junior list""" """ junior list"""
info = {'user': request.user, 'email': request.data['email'], 'first_name': request.data['first_name'], info = {'user': request.user, 'email': request.data['email'], 'first_name': request.data['first_name'],
'last_name': request.data['last_name']} 'last_name': request.data['last_name']}
# use AddJuniorSerializer serializer
serializer = AddJuniorSerializer(data=request.data, context=info) serializer = AddJuniorSerializer(data=request.data, context=info)
if serializer.is_valid(): if serializer.is_valid():
# save serializer
serializer.save() serializer.save()
return custom_response(SUCCESS_CODE['3021'], serializer.data, response_status=status.HTTP_200_OK) return custom_response(SUCCESS_CODE['3021'], serializer.data, response_status=status.HTTP_200_OK)
return custom_error_response(serializer.error, response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(serializer.error, response_status=status.HTTP_400_BAD_REQUEST)
@ -105,6 +131,7 @@ class InvitedJuniorAPIView(viewsets.ModelViewSet):
queryset = self.get_queryset() queryset = self.get_queryset()
paginator = self.pagination_class() paginator = self.pagination_class()
paginated_queryset = paginator.paginate_queryset(queryset, request) paginated_queryset = paginator.paginate_queryset(queryset, request)
# use JuniorDetailListSerializer serializer
serializer = JuniorDetailListSerializer(paginated_queryset, many=True) serializer = JuniorDetailListSerializer(paginated_queryset, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
@ -128,7 +155,9 @@ class FilterJuniorAPIView(viewsets.ModelViewSet):
"""Create guardian profile""" """Create guardian profile"""
queryset = self.get_queryset() queryset = self.get_queryset()
paginator = self.pagination_class() paginator = self.pagination_class()
# use Pagination
paginated_queryset = paginator.paginate_queryset(queryset, request) paginated_queryset = paginator.paginate_queryset(queryset, request)
# use JuniorDetailListSerializer serializer
serializer = JuniorDetailListSerializer(paginated_queryset, many=True) serializer = JuniorDetailListSerializer(paginated_queryset, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
@ -142,11 +171,14 @@ class RemoveJuniorAPIView(views.APIView):
def put(self, request, format=None): def put(self, request, format=None):
junior_id = self.request.GET.get('id') junior_id = self.request.GET.get('id')
guardian = Guardian.objects.filter(user__email=self.request.user).last() guardian = Guardian.objects.filter(user__email=self.request.user).last()
# fetch junior query
junior_queryset = Junior.objects.filter(id=junior_id, guardian_code__icontains=str(guardian.guardian_code), junior_queryset = Junior.objects.filter(id=junior_id, guardian_code__icontains=str(guardian.guardian_code),
is_invited=True).last() is_invited=True).last()
if junior_queryset: if junior_queryset:
# use RemoveJuniorSerializer serializer
serializer = RemoveJuniorSerializer(junior_queryset, data=request.data, partial=True) serializer = RemoveJuniorSerializer(junior_queryset, data=request.data, partial=True)
if serializer.is_valid(): if serializer.is_valid():
# save serializer
serializer.save() serializer.save()
return custom_response(SUCCESS_CODE['3022'], serializer.data, response_status=status.HTTP_200_OK) return custom_response(SUCCESS_CODE['3022'], serializer.data, response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)

View File

@ -9,13 +9,14 @@ https://docs.djangoproject.com/en/3.0/topics/settings/
For the full list of settings and their values, see For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/ https://docs.djangoproject.com/en/3.0/ref/settings/
""" """
# Django Import
import os import os
from dotenv import load_dotenv from dotenv import load_dotenv
from datetime import timedelta from datetime import timedelta
load_dotenv() load_dotenv()
# OR, the same with increased verbosity: # OR, the same with increased verbosity:
load_dotenv(verbose=True) load_dotenv(verbose=True)
# env path
env_path = os.path.join(os.path.abspath(os.path.join('.env', os.pardir)), '.env') env_path = os.path.join(os.path.abspath(os.path.join('.env', os.pardir)), '.env')
load_dotenv(dotenv_path=env_path) load_dotenv(dotenv_path=env_path)
@ -34,24 +35,28 @@ SECRET_KEY = '-pb+8w#)6qsh+w&tr+q$tholf7=54v%05e^9!lneiqqgtddg6q'
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
# allow all host
ALLOWED_HOSTS = ['*'] ALLOWED_HOSTS = ['*']
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
# Add your installed Django apps here
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
# Add Django rest frame work apps here
'django_extensions', 'django_extensions',
'storages', 'storages',
'drf_yasg', 'drf_yasg',
'corsheaders', 'corsheaders',
'django.contrib.postgres', 'django.contrib.postgres',
'rest_framework', 'rest_framework',
# Add your custom apps here.
'django_ses', 'django_ses',
'account', 'account',
'junior', 'junior',
@ -59,8 +64,9 @@ INSTALLED_APPS = [
'web_admin', 'web_admin',
# 'social_django' # 'social_django'
] ]
# define middle ware here
MIDDLEWARE = [ MIDDLEWARE = [
# Add your middleware classes here.
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
@ -68,10 +74,13 @@ MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'account.custom_middleware.CustomMiddleware'
] ]
# define root
ROOT_URLCONF = 'zod_bank.urls' ROOT_URLCONF = 'zod_bank.urls'
# define templates
TEMPLATES = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
@ -88,7 +97,9 @@ TEMPLATES = [
}, },
] ]
# define wsgi
WSGI_APPLICATION = 'zod_bank.wsgi.application' WSGI_APPLICATION = 'zod_bank.wsgi.application'
# define rest frame work
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [ 'DEFAULT_AUTHENTICATION_CLASSES': [
# 'rest_framework.authentication.SessionAuthentication', # 'rest_framework.authentication.SessionAuthentication',
@ -97,9 +108,10 @@ REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 5, 'PAGE_SIZE': 5,
} }
# define jwt token
SIMPLE_JWT = { SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=50), 'ACCESS_TOKEN_LIFETIME': timedelta(hours=2, minutes=59, seconds=59, microseconds=999999),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7), 'REFRESH_TOKEN_LIFETIME': timedelta(hours=71, minutes=59, seconds=59, microseconds=999999),
} }
# Database # Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases # https://docs.djangoproject.com/en/3.0/ref/settings/#databases
@ -113,7 +125,7 @@ DATABASES = {
'PORT':os.getenv('DB_PORT'), 'PORT':os.getenv('DB_PORT'),
} }
} }
# define swagger setting
SWAGGER_SETTINGS = { SWAGGER_SETTINGS = {
"exclude_namespaces": [], "exclude_namespaces": [],
"api_version": '0.1', "api_version": '0.1',
@ -140,6 +152,7 @@ SWAGGER_SETTINGS = {
# Password validation # Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
# password validation
AUTH_PASSWORD_VALIDATORS = [ AUTH_PASSWORD_VALIDATORS = [
{ {
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
@ -159,20 +172,23 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/ # https://docs.djangoproject.com/en/3.0/topics/i18n/
# language code
LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = 'en-us'
# time zone
TIME_ZONE = 'UTC' TIME_ZONE = 'UTC'
# define I18N
USE_I18N = True USE_I18N = True
# define L10N
USE_L10N = True USE_L10N = True
# define TZ
USE_TZ = True USE_TZ = True
# cors header settings # cors header settings
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# cors allow setting
CORS_ORIGIN_ALLOW_ALL = True CORS_ORIGIN_ALLOW_ALL = True
# cors allow method
CORS_ALLOW_METHODS = ( CORS_ALLOW_METHODS = (
'DELETE', 'DELETE',
'GET', 'GET',
@ -181,7 +197,7 @@ CORS_ALLOW_METHODS = (
'POST', 'POST',
'PUT', 'PUT',
) )
# cors allow header
CORS_ALLOW_HEADERS = ( CORS_ALLOW_HEADERS = (
'accept', 'accept',
'accept-encoding', 'accept-encoding',
@ -197,11 +213,12 @@ CORS_ALLOW_HEADERS = (
"""Static files (CSS, JavaScript, Images) """Static files (CSS, JavaScript, Images)
https://docs.djangoproject.com/en/3.0/howto/static-files/""" https://docs.djangoproject.com/en/3.0/howto/static-files/"""
# google client id
GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID') GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID')
# google client secret key
GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET') GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET')
# email settings
EMAIL_BACKEND="django.core.mail.backends.smtp.EmailBackend" EMAIL_BACKEND="django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST="smtp.sendgrid.net" EMAIL_HOST="smtp.sendgrid.net"
EMAIL_PORT="587" EMAIL_PORT="587"
@ -211,15 +228,16 @@ EMAIL_HOST_PASSWORD="SG.HAMnFRvaSMWeVLatqr4seg.Y9fQb-ckK9gyXLoMKdUE8eCh5lrel36Tm
EMAIL_FROM_ADDRESS="support@zodbank.com" EMAIL_FROM_ADDRESS="support@zodbank.com"
DEFAULT_ADDRESS="zodbank@yopmail.com" DEFAULT_ADDRESS="zodbank@yopmail.com"
# ali baba cloud settings
ALIYUN_OSS_ACCESS_KEY_ID = os.getenv('ALIYUN_OSS_ACCESS_KEY_ID') 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_ACCESS_KEY_SECRET = os.getenv('ALIYUN_OSS_ACCESS_KEY_SECRET')
ALIYUN_OSS_BUCKET_NAME = os.getenv('ALIYUN_OSS_BUCKET_NAME') ALIYUN_OSS_BUCKET_NAME = os.getenv('ALIYUN_OSS_BUCKET_NAME')
ALIYUN_OSS_ENDPOINT = os.getenv('ALIYUN_OSS_ENDPOINT') ALIYUN_OSS_ENDPOINT = os.getenv('ALIYUN_OSS_ENDPOINT')
ALIYUN_OSS_REGION = os.getenv('ALIYUN_OSS_REGION') ALIYUN_OSS_REGION = os.getenv('ALIYUN_OSS_REGION')
# define static url
STATIC_URL = 'static/' STATIC_URL = 'static/'
# define static root
STATIC_ROOT = 'static' STATIC_ROOT = 'static'
MEDIA_URL = "/media/" MEDIA_URL = "/media/"