diff --git a/account/serializers.py b/account/serializers.py index 4583b6a..3596c07 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -1,9 +1,10 @@ """Account serializer""" """Django Import""" -import random +# Import Refresh token of jwt from rest_framework import serializers from django.contrib.auth.models import User from rest_framework_simplejwt.tokens import RefreshToken +import secrets """App import""" # Import guardian's model, # Import junior's model, @@ -18,8 +19,8 @@ from rest_framework_simplejwt.tokens import RefreshToken from guardian.models import Guardian from junior.models import Junior from account.models import UserEmailOtp, DefaultTaskImages, UserDelete, UserNotification, UserPhoneOtp -from base.constants import GUARDIAN, JUNIOR, SUPERUSER -from base.messages import ERROR_CODE_REQUIRED, ERROR_CODE, SUCCESS_CODE, STATUS_CODE_ERROR +from base.constants import GUARDIAN, JUNIOR, SUPERUSER, NUMBER +from base.messages import ERROR_CODE, SUCCESS_CODE, STATUS_CODE_ERROR from .utils import delete_user_account_condition_social, delete_user_account_condition # In this serializer file @@ -90,6 +91,7 @@ class ResetPasswordSerializer(serializers.Serializer): def create(self, validated_data): verification_code = validated_data.pop('verification_code') 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() if user_opt_details: user_details = User.objects.filter(email=user_opt_details.email).last() @@ -112,6 +114,7 @@ class ChangePasswordSerializer(serializers.Serializer): def validate_current_password(self, value): user = self.context + # check old password if self.context.password not in ('', None) and user.check_password(value): return value raise serializers.ValidationError(ERROR_CODE['2015']) @@ -170,9 +173,9 @@ class GuardianSerializer(serializers.ModelSerializer): def get_user_type(self, obj): """user type""" 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 '2' + return str(NUMBER['two']) def get_auth(self, obj): """user email address""" @@ -217,7 +220,7 @@ class JuniorSerializer(serializers.ModelSerializer): email_verified = UserEmailOtp.objects.filter(email=obj.auth.username).last() if email_verified and email_verified.user_type is not None: return email_verified.user_type - return '1' + return str(NUMBER['one']) def get_auth(self, obj): return obj.auth.username @@ -251,6 +254,7 @@ class DefaultTaskImagesSerializer(serializers.ModelSerializer): model = DefaultTaskImages fields = ['id', 'task_name', 'image_url'] def create(self, validated_data): + # create default task object data = DefaultTaskImages.objects.create(**validated_data) return data @@ -273,10 +277,11 @@ class UserDeleteSerializer(serializers.ModelSerializer): data = validated_data.get('reason') passwd = self.context['password'] 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_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 instance = delete_user_account_condition(user, user_type_data, user_type, user_tb, data, random_num) return instance @@ -305,6 +310,7 @@ class UpdateUserNotificationSerializer(serializers.ModelSerializer): def create(self, validated_data): instance = UserNotification.objects.filter(user=self.context).last() if instance: + # change notification status instance.push_notification = validated_data.get('push_notification',instance.push_notification) instance.email_notification = validated_data.get('email_notification', instance.email_notification) instance.sms_notification = validated_data.get('sms_notification', instance.sms_notification) diff --git a/account/utils.py b/account/utils.py index eeb6954..9aca671 100644 --- a/account/utils.py +++ b/account/utils.py @@ -10,6 +10,7 @@ import string from datetime import datetime from calendar import timegm from uuid import uuid4 +# Import secrets module for generating random number import secrets from rest_framework import serializers # Django App Import @@ -55,6 +56,7 @@ def delete_user_account_condition(user, user_type_data, user_type, user_tb, data user_tb.username = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower() d_email = user_tb.email o_mail = user.email + # update user email with dummy email user_tb.save() """create object in user delete model""" instance = UserDelete.objects.create(user=user_tb, d_email=d_email, old_email=o_mail, @@ -74,6 +76,7 @@ def delete_user_account_condition_social(user, user_type,user_tb, data, random_n user_tb.username = str(random_num) + str('@D_') + '{}'.format(user_tb.username).lower() dummy_email = user_tb.email old_mail = user.email + # update user email with dummy email 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, @@ -84,6 +87,7 @@ def junior_account_update(user_tb): """junior account delete""" junior_data = Junior.objects.filter(auth__email=user_tb.email).first() if junior_data: + # Update junior account junior_data.is_active = False junior_data.is_verified = False junior_data.guardian_code = '{}' @@ -93,6 +97,7 @@ def guardian_account_update(user_tb): """update guardian account after delete the user account""" guardian_data = Guardian.objects.filter(user__email=user_tb.email).first() if guardian_data: + # Update guardian account guardian_data.is_active = False guardian_data.is_verified = False guardian_data.save() diff --git a/base/constants.py b/base/constants.py index 648bdd8..d8ca8a8 100644 --- a/base/constants.py +++ b/base/constants.py @@ -21,31 +21,10 @@ GRD = 'GRD' NUMBER = { 'point_zero': 0.0, 'zero': 0, 'one': 1, 'two': 2, 'three': 3, 'four': 4, '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 + 'sixteen': 16, 'seventeen': 17, 'eighteen': 18, 'nineteen': 19, 'twenty': 20, + 'twenty_one': 21, 'twenty_two': 22,'twenty_three': 23, 'twenty_four': 24, 'twenty_five': 25, + 'thirty': 30, 'forty': 40, 'fifty': 50, 'sixty': 60, 'seventy': 70, 'eighty': 80, 'ninty': 90, + 'ninety_nine': 99, 'hundred': 100, } @@ -65,10 +44,6 @@ FILE_SIZE = 5 * 1024 * 1024 # String constant for configurable date for allocation lock period ALLOCATION_LOCK_DATE = 1 -sort_dict = { - '1': 'name', - '2': '-name' -} """user type""" USER_TYPE = ( ('1', 'junior'), @@ -80,7 +55,7 @@ GENDERS = ( ('1', 'Male'), ('2', 'Female') ) -"""Task status""" +# Task status""" TASK_STATUS = ( ('1', 'pending'), ('2', 'in-progress'), @@ -88,13 +63,13 @@ TASK_STATUS = ( ('4', 'requested'), ('5', 'completed') ) -"""sign up method""" +# sign up method SIGNUP_METHODS = ( ('1', 'manual'), ('2', 'google'), ('3', 'apple') ) -"""relationship""" +# relationship RELATIONSHIP = ( ('1', 'parent'), ('2', 'legal_guardian') @@ -110,6 +85,7 @@ COMPLETED = 5 TASK_POINTS = 5 # duplicate name used defined in constant PROJECT_NAME PROJECT_NAME = 'Zod Bank' +# define user type constant GUARDIAN = 'guardian' JUNIOR = 'junior' SUPERUSER = 'superuser' diff --git a/base/messages.py b/base/messages.py index e3399ed..8b65d2a 100644 --- a/base/messages.py +++ b/base/messages.py @@ -62,7 +62,8 @@ ERROR_CODE = { "2035": "Image should not be 0 kb", "2036": "Choose valid user", # log in multiple device msg - "2037": "You are already log in another device" + "2037": "You are already log in another device", + "2038": "Choose valid action for task" } """Success message code""" SUCCESS_CODE = { @@ -98,8 +99,10 @@ SUCCESS_CODE = { "3020": "Logged out successfully.", "3021": "Add junior successfully", "3022": "Remove junior successfully", - "3023": "Approved junior successfully", - "3024": "Reject junior request 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 = { diff --git a/guardian/models.py b/guardian/models.py index 5636a80..1746c44 100644 --- a/guardian/models.py +++ b/guardian/models.py @@ -8,6 +8,33 @@ from base.constants import GENDERS, TASK_STATUS, PENDING, TASK_POINTS, SIGNUP_ME from junior.models import Junior """Add 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. class Guardian(models.Model): diff --git a/guardian/serializers.py b/guardian/serializers.py index 055d738..8bcd0cf 100644 --- a/guardian/serializers.py +++ b/guardian/serializers.py @@ -1,20 +1,41 @@ """Serializer of Guardian""" """Third party Django app""" import logging -import random from rest_framework import serializers +# Import Refresh token of jwt from rest_framework_simplejwt.tokens import RefreshToken from django.db import transaction from django.contrib.auth.models import User """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 account.models import UserProfile, UserEmailOtp, UserNotification from account.utils import generate_code -from account.serializers import JuniorSerializer from junior.serializers import JuniorDetailSerializer from base.messages import ERROR_CODE, SUCCESS_CODE from base.constants import NUMBER, JUN, ZOD, GRD 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): """User serializer""" auth_token = serializers.SerializerMethodField('get_auth_token') @@ -38,10 +59,12 @@ class UserSerializer(serializers.ModelSerializer): """Create user profile""" user = User.objects.create_user(username=email, email=email, password=password) UserNotification.objects.create(user=user) - if user_type == '1': + if user_type == str(NUMBER['one']): + # create junior profile Junior.objects.create(auth=user, junior_code=generate_code(JUN, user.id), referral_code=generate_code(ZOD, user.id)) - if user_type == '2': + if user_type == str(NUMBER['two']): + # create guardian profile Guardian.objects.create(user=user, guardian_code=generate_code(GRD, user.id), referral_code=generate_code(ZOD, user.id)) return user @@ -56,6 +79,7 @@ class UserSerializer(serializers.ModelSerializer): "code": 400, "status":"failed", }) +# update guardian profile class CreateGuardianSerializer(serializers.ModelSerializer): """Create guardian serializer""" """Basic info""" @@ -65,9 +89,12 @@ class CreateGuardianSerializer(serializers.ModelSerializer): """Contact details""" phone = serializers.CharField(max_length=20, required=False) country_code = serializers.IntegerField(required=False) + # basic info family_name = serializers.CharField(max_length=100, required=False) dob = serializers.DateField(required=False) + # code info referral_code = serializers.CharField(max_length=100, required=False) + # image info image = serializers.URLField(required=False) class Meta(object): @@ -140,6 +167,7 @@ class TaskSerializer(serializers.ModelSerializer): def create(self, validated_data): """create default task image data""" validated_data['guardian'] = Guardian.objects.filter(user=self.context['user']).last() + # update image of the task images = self.context['image'] validated_data['default_image'] = images instance = JuniorTask.objects.create(**validated_data) @@ -227,6 +255,7 @@ class GuardianProfileSerializer(serializers.ModelSerializer): """total filled fields count""" total_field_list = [obj.user.first_name, obj.country_name, 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] return len(total_complete_field) @@ -256,4 +285,24 @@ class ApproveJuniorSerializer(serializers.ModelSerializer): 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 diff --git a/guardian/urls.py b/guardian/urls.py index 71d3036..b14aa77 100644 --- a/guardian/urls.py +++ b/guardian/urls.py @@ -2,7 +2,7 @@ """Django import""" from django.urls import path, include from .views import (SignupViewset, UpdateGuardianProfile, AllTaskListAPIView, CreateTaskAPIView, TaskListAPIView, - SearchTaskListAPIView, TopJuniorListAPIView, ApproveJuniorAPIView) + SearchTaskListAPIView, TopJuniorListAPIView, ApproveJuniorAPIView, ApproveTaskAPIView) """Third party import""" from rest_framework import routers @@ -34,6 +34,8 @@ router.register('top-junior', TopJuniorListAPIView, basename='top-junior') router.register('filter-task', SearchTaskListAPIView, basename='filter-task') # 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 = [ path('api/v1/', include(router.urls)), diff --git a/guardian/views.py b/guardian/views.py index f35ca90..f53dc7d 100644 --- a/guardian/views.py +++ b/guardian/views.py @@ -5,14 +5,24 @@ from rest_framework import viewsets, status from rest_framework.pagination import PageNumberPagination from django.contrib.auth.models import User from django.utils import timezone -from PIL import Image -from datetime import datetime, timedelta """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, - TopJuniorSerializer, ApproveJuniorSerializer) + TopJuniorSerializer, ApproveJuniorSerializer, ApproveTaskSerializer) from .models import Guardian, JuniorTask from junior.models import Junior, JuniorPoints -from junior.serializers import JuniorDetailSerializer from account.models import UserEmailOtp, UserNotification from .tasks import generate_otp from account.utils import send_otp_email @@ -20,7 +30,17 @@ from account.utils import custom_response, custom_error_response from base.messages import ERROR_CODE, SUCCESS_CODE from base.constants import NUMBER 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. class SignupViewset(viewsets.ModelViewSet): """Signup view set""" @@ -35,6 +55,7 @@ class SignupViewset(viewsets.ModelViewSet): """Generate otp""" otp = generate_otp() expiry = timezone.now() + timezone.timedelta(days=1) + # create user email otp object UserEmailOtp.objects.create(email=request.data['email'], otp=otp, user_type=str(request.data['user_type']), expired_at=expiry) """Send email to the register user""" @@ -60,6 +81,7 @@ class UpdateGuardianProfile(viewsets.ViewSet): 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}" + # upload image on ali baba image_url = upload_image_to_alibaba(image, filename) data = {"image":image_url} serializer = CreateGuardianSerializer(context={"user":request.user, @@ -83,6 +105,7 @@ class AllTaskListAPIView(viewsets.ModelViewSet): def list(self, request, *args, **kwargs): """Create guardian profile""" queryset = JuniorTask.objects.filter(guardian__user=request.user) + # use TaskDetailsSerializer serializer serializer = TaskDetailsSerializer(queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) @@ -102,7 +125,9 @@ class TaskListAPIView(viewsets.ModelViewSet): queryset = JuniorTask.objects.filter(guardian__user=request.user, task_status=status_value).order_by('due_date','created_at') paginator = self.pagination_class() + # use Pagination paginated_queryset = paginator.paginate_queryset(queryset, request) + # use TaskDetailsSerializer serializer serializer = TaskDetailsSerializer(paginated_queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) @@ -123,8 +148,10 @@ class CreateTaskAPIView(viewsets.ModelViewSet): image_url = upload_image_to_alibaba(image, filename) image_data = image_url data.pop('default_image') + # use TaskSerializer serializer serializer = TaskSerializer(context={"user":request.user, "image":image_data}, data=data) if serializer.is_valid(): + # save serializer serializer.save() return custom_response(SUCCESS_CODE['3018'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) @@ -139,6 +166,7 @@ class SearchTaskListAPIView(viewsets.ModelViewSet): def get_queryset(self): """Get the queryset for the view""" title = self.request.GET.get('title') + # fetch junior query junior_queryset = JuniorTask.objects.filter(guardian__user=self.request.user, task_name__icontains=title)\ .order_by('due_date', 'created_at') return junior_queryset @@ -149,7 +177,7 @@ class SearchTaskListAPIView(viewsets.ModelViewSet): paginator = self.pagination_class() paginated_queryset = paginator.paginate_queryset(queryset, request) - + # use TaskSerializer serializer serializer = TaskDetailsSerializer(paginated_queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) @@ -186,18 +214,53 @@ class ApproveJuniorAPIView(viewsets.ViewSet): 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_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(): + 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(): + 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) diff --git a/junior/views.py b/junior/views.py index 5766c82..d77727b 100644 --- a/junior/views.py +++ b/junior/views.py @@ -2,9 +2,19 @@ from rest_framework import viewsets, status, generics,views from rest_framework.permissions import IsAuthenticated from rest_framework.pagination import PageNumberPagination -from rest_framework.response import Response -from PIL import Image """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 .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer,\ RemoveJuniorSerializer) @@ -13,6 +23,17 @@ from base.messages import ERROR_CODE, SUCCESS_CODE from base.constants import NUMBER from account.utils import custom_response, custom_error_response 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. class UpdateJuniorProfile(viewsets.ViewSet): """Update junior profile""" @@ -29,6 +50,7 @@ class UpdateJuniorProfile(viewsets.ViewSet): if image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) filename = f"images/{image.name}" + # upload image on ali baba image_url = upload_image_to_alibaba(image, filename) request_data = {"image": image_url} serializer = CreateJuniorSerializer(context={"user":request.user, "image":image_url, @@ -51,6 +73,7 @@ class ValidateGuardianCode(viewsets.ViewSet): """check guardian code""" guardian_code = self.request.GET.get('guardian_code').split(',') for code in guardian_code: + # fetch guardian object guardian_data = Guardian.objects.filter(guardian_code=code).exists() if guardian_data: return custom_response(SUCCESS_CODE['3013'], response_status=status.HTTP_200_OK) @@ -68,6 +91,7 @@ class JuniorListAPIView(viewsets.ModelViewSet): """ junior list""" guardian_data = Guardian.objects.filter(user__email=request.user).last() queryset = Junior.objects.filter(guardian_code__icontains=str(guardian_data.guardian_code)) + # use JuniorDetailListSerializer serializer serializer = JuniorDetailListSerializer(queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) @@ -80,8 +104,10 @@ class AddJuniorAPIView(viewsets.ModelViewSet): """ junior list""" info = {'user': request.user, 'email': request.data['email'], 'first_name': request.data['first_name'], 'last_name': request.data['last_name']} + # use AddJuniorSerializer serializer serializer = AddJuniorSerializer(data=request.data, context=info) if serializer.is_valid(): + # save serializer serializer.save() return custom_response(SUCCESS_CODE['3021'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.error, response_status=status.HTTP_400_BAD_REQUEST) @@ -105,6 +131,7 @@ class InvitedJuniorAPIView(viewsets.ModelViewSet): queryset = self.get_queryset() paginator = self.pagination_class() paginated_queryset = paginator.paginate_queryset(queryset, request) + # use JuniorDetailListSerializer serializer serializer = JuniorDetailListSerializer(paginated_queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) @@ -128,7 +155,9 @@ class FilterJuniorAPIView(viewsets.ModelViewSet): """Create guardian profile""" queryset = self.get_queryset() paginator = self.pagination_class() + # use Pagination paginated_queryset = paginator.paginate_queryset(queryset, request) + # use JuniorDetailListSerializer serializer serializer = JuniorDetailListSerializer(paginated_queryset, many=True) 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): junior_id = self.request.GET.get('id') guardian = Guardian.objects.filter(user__email=self.request.user).last() + # fetch junior query junior_queryset = Junior.objects.filter(id=junior_id, guardian_code__icontains=str(guardian.guardian_code), is_invited=True).last() if junior_queryset: + # use RemoveJuniorSerializer serializer serializer = RemoveJuniorSerializer(junior_queryset, data=request.data, partial=True) if serializer.is_valid(): + # save serializer serializer.save() 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) diff --git a/zod_bank/settings.py b/zod_bank/settings.py index b052a4f..84191b0 100644 --- a/zod_bank/settings.py +++ b/zod_bank/settings.py @@ -9,13 +9,14 @@ https://docs.djangoproject.com/en/3.0/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/3.0/ref/settings/ """ - +# Django Import import os from dotenv import load_dotenv from datetime import timedelta load_dotenv() # OR, the same with increased verbosity: load_dotenv(verbose=True) +# env path env_path = os.path.join(os.path.abspath(os.path.join('.env', os.pardir)), '.env') load_dotenv(dotenv_path=env_path) @@ -34,32 +35,36 @@ SECRET_KEY = '-pb+8w#)6qsh+w&tr+q$tholf7=54v%05e^9!lneiqqgtddg6q' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True +# allow all host ALLOWED_HOSTS = ['*'] # Application definition INSTALLED_APPS = [ + # Add your installed Django apps here 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + # Add Django rest frame work apps here 'django_extensions', 'storages', 'drf_yasg', 'corsheaders', 'django.contrib.postgres', 'rest_framework', + # Add your custom apps here. 'django_ses', 'account', 'junior', - 'guardian', - # 'social_django' + 'guardian' ] - +# define middle ware here MIDDLEWARE = [ + # Add your middleware classes here. 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', @@ -70,8 +75,10 @@ MIDDLEWARE = [ 'account.custom_middleware.CustomMiddleware' ] +# define root ROOT_URLCONF = 'zod_bank.urls' +# define templates TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', @@ -88,7 +95,9 @@ TEMPLATES = [ }, ] +# define wsgi WSGI_APPLICATION = 'zod_bank.wsgi.application' +# define rest frame work REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ # 'rest_framework.authentication.SessionAuthentication', @@ -97,6 +106,7 @@ REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 5, } +# define jwt token SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(hours=2, minutes=59, seconds=59, microseconds=999999), 'REFRESH_TOKEN_LIFETIME': timedelta(hours=71, minutes=59, seconds=59, microseconds=999999), @@ -113,7 +123,7 @@ DATABASES = { 'PORT':os.getenv('DB_PORT'), } } - +# define swagger setting SWAGGER_SETTINGS = { "exclude_namespaces": [], "api_version": '0.1', @@ -140,6 +150,7 @@ SWAGGER_SETTINGS = { # Password validation # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators +# password validation AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', @@ -159,20 +170,23 @@ AUTH_PASSWORD_VALIDATORS = [ # Internationalization # https://docs.djangoproject.com/en/3.0/topics/i18n/ +# language code LANGUAGE_CODE = 'en-us' - +# time zone TIME_ZONE = 'UTC' - +# define I18N USE_I18N = True - +# define L10N USE_L10N = True - +# define TZ USE_TZ = True # cors header settings SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +# cors allow setting CORS_ORIGIN_ALLOW_ALL = True +# cors allow method CORS_ALLOW_METHODS = ( 'DELETE', 'GET', @@ -181,7 +195,7 @@ CORS_ALLOW_METHODS = ( 'POST', 'PUT', ) - +# cors allow header CORS_ALLOW_HEADERS = ( 'accept', 'accept-encoding', @@ -197,11 +211,12 @@ CORS_ALLOW_HEADERS = ( """Static files (CSS, JavaScript, Images) https://docs.djangoproject.com/en/3.0/howto/static-files/""" - +# google client id GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID') +# google client secret key GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET') - +# email settings EMAIL_BACKEND="django.core.mail.backends.smtp.EmailBackend" EMAIL_HOST="smtp.sendgrid.net" EMAIL_PORT="587" @@ -211,14 +226,15 @@ EMAIL_HOST_PASSWORD="SG.HAMnFRvaSMWeVLatqr4seg.Y9fQb-ckK9gyXLoMKdUE8eCh5lrel36Tm EMAIL_FROM_ADDRESS="support@zodbank.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_SECRET = os.getenv('ALIYUN_OSS_ACCESS_KEY_SECRET') ALIYUN_OSS_BUCKET_NAME = os.getenv('ALIYUN_OSS_BUCKET_NAME') ALIYUN_OSS_ENDPOINT = os.getenv('ALIYUN_OSS_ENDPOINT') ALIYUN_OSS_REGION = os.getenv('ALIYUN_OSS_REGION') - +# define static url STATIC_URL = 'static/' +# define static root STATIC_ROOT = 'static'