diff --git a/zod_bank/Dockerfile b/zod_bank/Dockerfile new file mode 100644 index 0000000..77c6fa8 --- /dev/null +++ b/zod_bank/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.9 +ENV PYTHONUNBUFFERED 1 +RUN mkdir /usr/src/app +WORKDIR /usr/src/app +COPY . . +RUN apt-get update +RUN apt-get install wkhtmltopdf -y +RUN apt install -y gdal-bin python3-gdal +RUN pip install -r requirements.txt +WORKDIR /usr/src/app + diff --git a/zod_bank/account/admin.py b/zod_bank/account/admin.py index fce7bde..7dbf869 100644 --- a/zod_bank/account/admin.py +++ b/zod_bank/account/admin.py @@ -1,10 +1,12 @@ +"""Account admin""" from django.contrib import admin -# Register your models here. +"""Import django app""" from .models import UserProfile, UserEmailOtp, UserPhoneOtp # Register your models here. @admin.register(UserProfile) class UserProfileAdmin(admin.ModelAdmin): + """User profile admin""" list_display = ['user'] def __str__(self): @@ -12,14 +14,18 @@ class UserProfileAdmin(admin.ModelAdmin): @admin.register(UserEmailOtp) class UserEmailOtpAdmin(admin.ModelAdmin): + """User Email otp admin""" list_display = ['email'] def __str__(self): + """Return object in email and otp format""" return self.email + '-' + self.otp @admin.register(UserPhoneOtp) class UserPhoneOtpAdmin(admin.ModelAdmin): + """User Phone otp admin""" list_display = ['phone'] def __str__(self): + """Return object in phone number and otp format""" return self.phone + '-' + self.otp diff --git a/zod_bank/account/utils.py b/zod_bank/account/utils.py index 2d86106..f20ef19 100644 --- a/zod_bank/account/utils.py +++ b/zod_bank/account/utils.py @@ -1,6 +1,6 @@ -from django.core.mail import send_mail +"""Account utils""" +"""Third party Django app""" from django.conf import settings -import random from rest_framework import viewsets, status from rest_framework.response import Response diff --git a/zod_bank/account/views.py b/zod_bank/account/views.py index e3a9550..c6f65ff 100644 --- a/zod_bank/account/views.py +++ b/zod_bank/account/views.py @@ -1,6 +1,7 @@ from rest_framework import viewsets, status, views from rest_framework.decorators import action import random +import logging from django.contrib.auth import authenticate, login from guardian.models import Guardian from junior.models import Junior @@ -8,11 +9,11 @@ from account.models import UserProfile, UserPhoneOtp, UserEmailOtp from django.contrib.auth.models import User from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer, ForgotPasswordSerializer, ResetPasswordSerializer, ChangePasswordSerializer) -from django.views.decorators.csrf import csrf_exempt from rest_framework_simplejwt.tokens import RefreshToken from base.messages import ERROR_CODE, SUCCESS_CODE from guardian.tasks import generate_otp from django.conf import settings +from account.utils import send_otp_email from account.utils import custom_response, custom_error_response from django.core.mail import EmailMessage from django.core.mail import send_mail @@ -27,7 +28,7 @@ class ChangePasswordAPIView(views.APIView): serializer = ChangePasswordSerializer(context=request.user, data=request.data) if serializer.is_valid(): serializer.save() - return custom_response(SUCCESS_CODE['3006'], response_status=status.HTTP_200_OK) + return custom_response(SUCCESS_CODE['3007'], response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) class ResetPasswordAPIView(views.APIView): @@ -59,11 +60,11 @@ class ForgotPasswordAPIView(views.APIView): 'verification_code': verification_code } ) - user_data = UserEmailOtp.objects.get_or_create(email=email) + user_data, created = UserEmailOtp.objects.get_or_create(email=email) if user_data: user_data.otp = verification_code user_data.save() - return custom_response(SUCCESS_CODE['3015'], {'verification_code': verification_code}, + return custom_response(SUCCESS_CODE['3015'], response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) @@ -86,15 +87,15 @@ class UserPhoneVerification(viewsets.ModelViewSet): """Send otp on phone""" def list(self, request, *args, **kwargs): try: - phone_data = UserPhoneOtp.objects.filter(phone=request.data['phone'], - otp=request.data['otp']).last() + phone_data = UserPhoneOtp.objects.filter(phone=self.request.GET.get('phone'), + otp=self.request.GET.get('otp')).last() if phone_data: phone_data.is_verified = True phone_data.save() return custom_response(SUCCESS_CODE['3012'], response_status=status.HTTP_200_OK) else: return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST) - except Exception as e: + except Exception: return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST) @@ -114,12 +115,11 @@ class UserLogin(viewsets.ViewSet): junior_data = Junior.objects.filter(auth__username=username, is_complete_profile=True).last() if junior_data: serializer = JuniorSerializer(junior_data) - if user.is_superuser: - serializer = SuperUserSerializer(user) return custom_response(SUCCESS_CODE['3003'], serializer.data, response_status=status.HTTP_200_OK) else: return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED) except Exception as e: + logging.error(e) user_profile_data = UserProfile.objects.filter(user__username=username).last() email_verified = UserEmailOtp.objects.filter(email=username).last() refresh = RefreshToken.for_user(user) @@ -140,14 +140,34 @@ class UserLogin(viewsets.ViewSet): data.update({"is_email_verified": is_verified}) return custom_response(None, data, response_status=status.HTTP_200_OK) + @action(methods=['post'], detail=False) + def admin_login(self, request): + username = request.data.get('username') + password = request.data.get('password') + user = authenticate(request, username=username, password=password) + try: + if user is not None: + login(request, user) + if user.is_superuser: + serializer = SuperUserSerializer(user) + return custom_response(SUCCESS_CODE['3003'], serializer.data, response_status=status.HTTP_200_OK) + else: + return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED) + except Exception as e: + logging.error(e) + refresh = RefreshToken.for_user(user) + access_token = str(refresh.access_token) + data = {"auth_token": access_token, "user_role": '3'} + return custom_response(None, data, response_status=status.HTTP_200_OK) + class UserEmailVerification(viewsets.ModelViewSet): """User Email verification""" serializer_class = EmailVerificationSerializer def list(self, request, *args, **kwargs): try: - email_data = UserEmailOtp.objects.filter(email=request.data['email'], - otp=request.data['otp']).last() + email_data = UserEmailOtp.objects.filter(email=self.request.GET.get('email'), + otp=self.request.GET.get('otp')).last() if email_data: email_data.is_verified = True email_data.save() @@ -155,6 +175,7 @@ class UserEmailVerification(viewsets.ModelViewSet): else: return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: + logging.error(e) return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST) class ReSendEmailOtp(viewsets.ModelViewSet): @@ -162,11 +183,12 @@ class ReSendEmailOtp(viewsets.ModelViewSet): def create(self, request, *args, **kwargs): otp = generate_otp() if User.objects.filter(email=request.data['email']): - email_data = UserEmailOtp.objects.get_or_create(email=request.data['email']) + email_data, created = UserEmailOtp.objects.get_or_create(email=request.data['email']) if email_data: email_data.otp = otp email_data.save() - return custom_response(None, {'email_otp': otp}, response_status=status.HTTP_200_OK) + send_otp_email(request.data['email'], otp) + return custom_response(SUCCESS_CODE['3016'], response_status=status.HTTP_200_OK) else: return custom_error_response(ERROR_CODE["2023"], response_status=status.HTTP_400_BAD_REQUEST) diff --git a/zod_bank/base/messages.py b/zod_bank/base/messages.py index 39f0282..37507fd 100644 --- a/zod_bank/base/messages.py +++ b/zod_bank/base/messages.py @@ -63,7 +63,7 @@ SUCCESS_CODE = { # Success code for password reset "3006": "Your password has been reset successfully.", # Success code for password update - "3007": "Your password has been updated successfully.", + "3007": "Your password has been changed successfully.", # Success code for valid link "3008": "You have a valid link.", # Success code for logged out @@ -74,7 +74,8 @@ SUCCESS_CODE = { "3012": "Phone OTP Verified successfully", "3013": "Valid Guardian code", "3014": "Password has been updated successfully.", - "3015": "Verification code sent on your email." + "3015": "Verification code sent on your email.", + "3016": "Send otp on your Email successfully" } STATUS_CODE_ERROR = { diff --git a/zod_bank/docker-compose.yml b/zod_bank/docker-compose.yml new file mode 100644 index 0000000..700bf1b --- /dev/null +++ b/zod_bank/docker-compose.yml @@ -0,0 +1,18 @@ +version: '3' +services: + nginx: + image: nginx:latest + container_name: nginx + ports: + - "8000:8000" + volumes: + - ./nginx:/etc/nginx/conf.d + - .:/usr/src/app + depends_on: + - web + web: + build: . + container_name: django + command: bash -c "pip install -r requirements.txt && python manage.py collectstatic --noinput && python manage.py migrate && gunicorn zod_bank.wsgi -b 0.0.0.0:8000 -t 300 --log-level=info" + volumes: + - .:/usr/src/app diff --git a/zod_bank/guardian/admin.py b/zod_bank/guardian/admin.py index f2c8fbc..a3bd40c 100644 --- a/zod_bank/guardian/admin.py +++ b/zod_bank/guardian/admin.py @@ -1,9 +1,14 @@ +"""Guardian admin""" +"""Third party Django app""" from django.contrib import admin +"""Import Django app""" from .models import Guardian # Register your models here. @admin.register(Guardian) class GuardianAdmin(admin.ModelAdmin): + """Junior Admin""" list_display = ['user', 'family_name'] def __str__(self): - return self.user__email \ No newline at end of file + """Return email id""" + return self.user__email diff --git a/zod_bank/guardian/apps.py b/zod_bank/guardian/apps.py index b69ed5d..fcaf209 100644 --- a/zod_bank/guardian/apps.py +++ b/zod_bank/guardian/apps.py @@ -1,6 +1,9 @@ +"""Guardian app file""" +"""Third party Django app""" from django.apps import AppConfig class CustodianConfig(AppConfig): + """Guardian config""" default_auto_field = 'django.db.models.BigAutoField' name = 'guardian' diff --git a/zod_bank/guardian/migrations/0002_remove_guardian_junior_code.py b/zod_bank/guardian/migrations/0002_remove_guardian_junior_code.py new file mode 100644 index 0000000..6996d0a --- /dev/null +++ b/zod_bank/guardian/migrations/0002_remove_guardian_junior_code.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.2 on 2023-06-27 06:15 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('guardian', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='guardian', + name='junior_code', + ), + ] diff --git a/zod_bank/guardian/models.py b/zod_bank/guardian/models.py index 03ce62a..f135bae 100644 --- a/zod_bank/guardian/models.py +++ b/zod_bank/guardian/models.py @@ -1,23 +1,31 @@ +"""Guardian model file""" +"""Third party Django app""" from django.db import models from django.contrib.auth import get_user_model +"""Import Django app""" from base.constants import GENDERS -from django.contrib.postgres.fields import ArrayField User = get_user_model() # Create your models here. class Guardian(models.Model): + """Guardian model""" user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='guardian_profile', verbose_name='Email') + """Contact details""" country_code = models.IntegerField(blank=True, null=True) phone = models.CharField(max_length=31, null=True, blank=True, default=None) + """Personal info""" family_name = models.CharField(max_length=50, null=True, blank=True, default=None) gender = models.CharField(choices=GENDERS, max_length=15, null=True, blank=True, default=None) dob = models.DateField(max_length=15, null=True, blank=True, default=None) + """Codes""" guardian_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_used = models.CharField(max_length=10, null=True, blank=True, default=None) + """Profile activity""" is_active = models.BooleanField(default=True) is_complete_profile = models.BooleanField(default=False) passcode = models.IntegerField(null=True, blank=True, default=None) + """Profile created and updated time""" created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) @@ -27,4 +35,5 @@ class Guardian(models.Model): verbose_name = 'Guardian' def __str__(self): + """Return email id""" return f'{self.user}' diff --git a/zod_bank/guardian/serializers.py b/zod_bank/guardian/serializers.py index e55c766..e2bd807 100644 --- a/zod_bank/guardian/serializers.py +++ b/zod_bank/guardian/serializers.py @@ -1,91 +1,116 @@ -from rest_framework import serializers -from django.contrib.auth.models import User -from .models import Guardian -from django.db import transaction +"""Serializer of Guardian""" +"""Third party Django app""" +import logging import random -from account.models import UserProfile -from junior.models import Junior -from base.constants import GENDERS, GUARDIAN, JUNIOR, SUPERUSER +from rest_framework import serializers from rest_framework_simplejwt.tokens import RefreshToken +from django.db import transaction +from django.contrib.auth.models import User +"""Import Django app""" +from .models import Guardian +from account.models import UserProfile from base.messages import ERROR_CODE, SUCCESS_CODE class UserSerializer(serializers.ModelSerializer): + """User serializer""" auth_token = serializers.SerializerMethodField('get_auth_token') - class Meta(object): + """Meta info""" model = User fields = ['email', 'password', 'auth_token'] def get_auth_token(self, obj): + """generate auth token""" refresh = RefreshToken.for_user(obj) access_token = str(refresh.access_token) return access_token def create(self, validated_data): + """fetch data""" email = validated_data.get('email') user_type = self.context password = validated_data.get('password') try: + """Create user profile""" user = User.objects.create_user(username=email, email=email, password=password) UserProfile.objects.create(user=user, user_type=user_type) return user - except: + except Exception as e: + """Error handling""" + logging.error(e) raise serializers.ValidationError({"details":ERROR_CODE['2021']}) def save(self, **kwargs): + """save the data""" with transaction.atomic(): instance = super().save(**kwargs) return instance class CreateGuardianSerializer(serializers.ModelSerializer): + """Create guardian serializer""" + """Basic info""" first_name = serializers.SerializerMethodField('get_first_name') last_name = serializers.SerializerMethodField('get_last_name') email = serializers.SerializerMethodField('get_email') + """Contact details""" phone = serializers.CharField(max_length=20, required=False) - family_name = serializers.CharField(max_length=100, required=False) country_code = serializers.IntegerField(required=False) + family_name = serializers.CharField(max_length=100, required=False) dob = serializers.DateField(required=False) referral_code = serializers.CharField(max_length=100, required=False) class Meta(object): + """Meta info""" model = Guardian - fields = ['first_name', 'last_name', 'email', 'phone', 'family_name', 'gender', 'country_code', 'dob', 'referral_code', 'passcode', - 'is_complete_profile'] + fields = ['first_name', 'last_name', 'email', 'phone', 'family_name', 'gender', 'country_code', + 'dob', 'referral_code', 'passcode', 'is_complete_profile'] def get_first_name(self,obj): + """first name of guardian""" return obj.user.first_name def get_last_name(self,obj): + """last name of guardian""" return obj.user.last_name def get_email(self,obj): + """emailof guardian""" return obj.user.email def create(self, validated_data): + """Create guardian profile""" user = User.objects.filter(username=self.context['user']).last() if user: + """Save first and last name of guardian""" user.first_name = self.context.get('first_name', user.first_name) user.last_name = self.context.get('last_name', user.last_name) user.save() + """Create guardian data""" guardian, created = Guardian.objects.get_or_create(user=self.context['user']) 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: - guardian.phone = validated_data.get('phone', guardian.phone) + """update details according to the data get from request""" guardian.gender = validated_data.get('gender',guardian.gender) guardian.family_name = validated_data.get('family_name', guardian.family_name) guardian.dob = validated_data.get('dob',guardian.dob) + """Update country code and phone number""" + guardian.phone = validated_data.get('phone', guardian.phone) + guardian.country_code = validated_data.get('country_code', guardian.country_code) guardian.passcode = validated_data.get('passcode', guardian.passcode) + guardian.referral_code_used = validated_data.get('referral_code_used', guardian.referral_code_used) + """Complete profile of the junior if below all data are filled""" complete_profile_field = all([guardian.phone, guardian.gender, guardian.family_name, guardian.dob, guardian.country_code, user.first_name, user.last_name]) guardian.is_complete_profile = False if complete_profile_field: guardian.is_complete_profile = True - guardian.country_code = validated_data.get('country_code', guardian.country_code) guardian.save() return guardian def save(self, **kwargs): + """Save the data into junior table""" with transaction.atomic(): instance = super().save(**kwargs) return instance diff --git a/zod_bank/guardian/tests.py b/zod_bank/guardian/tests.py index 7ce503c..3036e8b 100644 --- a/zod_bank/guardian/tests.py +++ b/zod_bank/guardian/tests.py @@ -1,3 +1,5 @@ +"""Test file of Guardian""" +"""Third party Django app""" from django.test import TestCase # Create your tests here. diff --git a/zod_bank/guardian/urls.py b/zod_bank/guardian/urls.py index 5adfc55..5399f2b 100644 --- a/zod_bank/guardian/urls.py +++ b/zod_bank/guardian/urls.py @@ -1,17 +1,19 @@ """ Urls files""" """Django import""" from django.urls import path, include -from rest_framework.decorators import api_view from .views import SignupViewset, UpdateGuardianProfile """Third party import""" from rest_framework import routers -"""Router""" +"""Define Router""" router = routers.SimpleRouter() """API End points with router""" +"""Sign up API""" router.register('sign-up', SignupViewset, basename='sign-up') +"""Create guardian profile API""" router.register('create-guardian-profile', UpdateGuardianProfile, basename='update-guardian-profile') +"""Define Url pattern""" urlpatterns = [ path('api/v1/', include(router.urls)), ] diff --git a/zod_bank/guardian/views.py b/zod_bank/guardian/views.py index 2b40702..72e5b94 100644 --- a/zod_bank/guardian/views.py +++ b/zod_bank/guardian/views.py @@ -1,45 +1,47 @@ -from django.shortcuts import render -from rest_framework import (pagination, viewsets, status, generics, mixins) -from .serializers import CreateGuardianSerializer -from rest_framework.decorators import action -from rest_framework.response import Response -from django.views.decorators.csrf import csrf_exempt -# Create your views here. -from rest_framework import viewsets, status -from rest_framework.response import Response -from .serializers import UserSerializer -from django.contrib.auth.models import User +"""Views of Guardian""" +"""Third party Django app""" from rest_framework.permissions import IsAuthenticated -from base.constants import GUARDIAN, JUNIOR, SUPERUSER -from junior.models import Junior +from rest_framework import viewsets, status +"""Import Django app""" +from .serializers import UserSerializer +from .serializers import CreateGuardianSerializer from account.models import UserEmailOtp from .tasks import generate_otp from account.utils import send_otp_email from account.utils import custom_response, custom_error_response from base.messages import ERROR_CODE, SUCCESS_CODE - +# Create your views here. class SignupViewset(viewsets.ModelViewSet): + """Signup view set""" serializer_class = UserSerializer def create(self, request, *args, **kwargs): + """Create user profile""" serializer = UserSerializer(context=request.data['user_type'], data=request.data) if serializer.is_valid(): serializer.save() + """Generate otp""" otp = generate_otp() UserEmailOtp.objects.create(email=request.data['email'], otp=otp) + """Send email to the register user""" send_otp_email(request.data['email'], otp) return custom_response(SUCCESS_CODE['3001'], {"email_otp": otp}, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) class UpdateGuardianProfile(viewsets.ViewSet): + """Update guardian profile""" serializer_class = CreateGuardianSerializer permission_classes = [IsAuthenticated] def create(self, request, *args, **kwargs): - serializer = CreateGuardianSerializer(context={"user":request.user,"first_name":request.data.get('first_name', ''), - "last_name": request.data.get('last_name',' ')}, data=request.data) + """Create guardian profile""" + serializer = CreateGuardianSerializer(context={"user":request.user, + "first_name":request.data.get('first_name', ''), + "last_name": request.data.get('last_name',' ')}, + data=request.data) if serializer.is_valid(): + """save serializer""" serializer.save() return custom_response(None, serializer.data,response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) diff --git a/zod_bank/junior/admin.py b/zod_bank/junior/admin.py index 07d6053..87cd7d8 100644 --- a/zod_bank/junior/admin.py +++ b/zod_bank/junior/admin.py @@ -1,9 +1,14 @@ +"""Junior admin""" +"""Third party Django app""" from django.contrib import admin +"""Import Django app""" from .models import Junior # Register your models here. @admin.register(Junior) class JuniorAdmin(admin.ModelAdmin): + """Junior Admin""" list_display = ['auth'] def __str__(self): + """Return email id""" return self.auth__email diff --git a/zod_bank/junior/apps.py b/zod_bank/junior/apps.py index 0232709..f3df25e 100644 --- a/zod_bank/junior/apps.py +++ b/zod_bank/junior/apps.py @@ -1,6 +1,8 @@ +"""App file""" +"""Import AppConfig""" from django.apps import AppConfig - class JuniorConfig(AppConfig): + """Junior config""" default_auto_field = 'django.db.models.BigAutoField' name = 'junior' diff --git a/zod_bank/junior/models.py b/zod_bank/junior/models.py index 43c9d74..732bb66 100644 --- a/zod_bank/junior/models.py +++ b/zod_bank/junior/models.py @@ -1,25 +1,33 @@ +"""Junior model """ +"""Import django""" from django.db import models from django.contrib.auth import get_user_model -from base.constants import GENDERS -from guardian.models import Guardian from django.contrib.postgres.fields import ArrayField +"""Import django app""" +from base.constants import GENDERS User = get_user_model() # Create your models here. class Junior(models.Model): + """Junior model""" auth = models.ForeignKey(User, on_delete=models.CASCADE, related_name='junior_profile', verbose_name='Email') + """Contact details""" phone = models.CharField(max_length=31, null=True, blank=True, default=None) country_code = models.IntegerField(blank=True, null=True) + """Personal info""" gender = models.CharField(max_length=10, choices=GENDERS, null=True, blank=True, default=None) dob = models.DateField(max_length=15, null=True, blank=True, default=None) # image = models.ImageField(upload_to='images/') + """Codes""" junior_code = models.CharField(max_length=10, null=True, blank=True, default=None) guardian_code = ArrayField(models.CharField(max_length=10, null=True, blank=True, default=None),null=True) referral_code = 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 activity""" is_active = models.BooleanField(default=True) is_complete_profile = models.BooleanField(default=False) passcode = models.IntegerField(null=True, blank=True, default=None) + """Profile created and updated time""" created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) @@ -29,4 +37,5 @@ class Junior(models.Model): verbose_name = 'Junior' def __str__(self): + """Return email id""" return f'{self.auth}' diff --git a/zod_bank/junior/serializers.py b/zod_bank/junior/serializers.py index 3e493e7..5d6df77 100644 --- a/zod_bank/junior/serializers.py +++ b/zod_bank/junior/serializers.py @@ -1,28 +1,29 @@ +"""Serializer file for junior""" +"""Import Django 3rd party app""" from rest_framework import serializers from django.contrib.auth.models import User -from .models import Guardian from django.db import transaction import random -from account.models import UserProfile +"""Import django app""" from junior.models import Junior -from base.constants import GENDERS, GUARDIAN, JUNIOR, SUPERUSER -from rest_framework_simplejwt.tokens import RefreshToken -from base.messages import ERROR_CODE, SUCCESS_CODE -from django.contrib.postgres.fields import ArrayField class ListCharField(serializers.ListField): + """Serializer for Array field""" child = serializers.CharField() def to_representation(self, data): + """to represent the data""" return data def to_internal_value(self, data): + """internal value""" if isinstance(data, list): return data raise serializers.ValidationError({"details":"Invalid input. Expected a list of strings."}) class CreateJuniorSerializer(serializers.ModelSerializer): + """Create junior serializer""" first_name = serializers.SerializerMethodField('get_first_name') last_name = serializers.SerializerMethodField('get_last_name') email = serializers.SerializerMethodField('get_email') @@ -33,41 +34,59 @@ class CreateJuniorSerializer(serializers.ModelSerializer): guardian_code = ListCharField(required=False) class Meta(object): + """Meta info""" model = Junior fields = ['first_name', 'last_name', 'email', 'phone', 'gender', 'country_code', 'dob', 'referral_code', 'passcode', 'is_complete_profile', 'guardian_code'] def get_first_name(self,obj): + """first name of junior""" return obj.auth.first_name def get_last_name(self,obj): + """last name of junior""" return obj.auth.last_name def get_email(self,obj): + """email of junior""" return obj.auth.email def create(self, validated_data): + """Create junior profile""" user = User.objects.filter(username=self.context['user']).last() if user: + """Save first and last name of junior""" user.first_name = self.context.get('first_name', user.first_name) user.last_name = self.context.get('last_name', user.last_name) user.save() + """Create junior data""" junior, created = Junior.objects.get_or_create(auth=self.context['user']) 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: - junior.phone = validated_data.get('phone', junior.phone) + """update details according to the data get from request""" junior.gender = validated_data.get('gender',junior.gender) + """Update guardian code""" junior.guardian_code = validated_data.get('guardian_code', junior.guardian_code) junior.dob = validated_data.get('dob',junior.dob) junior.passcode = validated_data.get('passcode', junior.passcode) - junior.is_complete_profile = validated_data.get('is_complete_profile', junior.is_complete_profile) + """Update country code and phone number""" + junior.phone = validated_data.get('phone', junior.phone) junior.country_code = validated_data.get('country_code', junior.country_code) + junior.referral_code_used = validated_data.get('referral_code_used', junior.referral_code_used) + """Complete profile of the junior if below all data are filled""" + complete_profile_field = all([junior.phone, junior.gender, junior.family_name, + junior.dob, junior.country_code, user.first_name, user.last_name]) + junior.is_complete_profile = False + if complete_profile_field: + junior.is_complete_profile = True junior.save() return junior def save(self, **kwargs): + """Save the data into junior table""" with transaction.atomic(): instance = super().save(**kwargs) return instance diff --git a/zod_bank/junior/tests.py b/zod_bank/junior/tests.py index 7ce503c..1a75974 100644 --- a/zod_bank/junior/tests.py +++ b/zod_bank/junior/tests.py @@ -1,3 +1,5 @@ +"""Junior test file""" +"""Import TestCase""" from django.test import TestCase # Create your tests here. diff --git a/zod_bank/junior/urls.py b/zod_bank/junior/urls.py index 1dc2e23..2b64fe4 100644 --- a/zod_bank/junior/urls.py +++ b/zod_bank/junior/urls.py @@ -1,7 +1,6 @@ """ Urls files""" """Django import""" from django.urls import path, include -from rest_framework.decorators import api_view from .views import UpdateJuniorProfile, ValidateGuardianCode """Third party import""" from rest_framework import routers @@ -10,8 +9,11 @@ from rest_framework import routers router = routers.SimpleRouter() """API End points with router""" +"""Create junior profile API""" router.register('create-junior-profile', UpdateJuniorProfile, basename='profile-update') +"""validate guardian code API""" router.register('validate-guardian-code', ValidateGuardianCode, basename='validate-guardian-code') +"""Define url pattern""" urlpatterns = [ path('api/v1/', include(router.urls)), ] diff --git a/zod_bank/junior/views.py b/zod_bank/junior/views.py index 7eb1063..153bb41 100644 --- a/zod_bank/junior/views.py +++ b/zod_bank/junior/views.py @@ -1,40 +1,40 @@ -from django.shortcuts import render -from rest_framework import (pagination, viewsets, status, generics, mixins) -from rest_framework.decorators import action -from rest_framework.response import Response -from django.views.decorators.csrf import csrf_exempt -# Create your views here. +"""Junior view file""" from rest_framework import viewsets, status -from rest_framework.response import Response -from .serializers import CreateJuniorSerializer -from django.contrib.auth.models import User from rest_framework.permissions import IsAuthenticated -from base.constants import GUARDIAN, JUNIOR, SUPERUSER +"""Django app import""" from junior.models import Junior +from .serializers import CreateJuniorSerializer from guardian.models import Guardian from base.messages import ERROR_CODE, SUCCESS_CODE from account.utils import custom_response, custom_error_response - +# Create your views here. class UpdateJuniorProfile(viewsets.ViewSet): + """Update junior profile""" serializer_class = CreateJuniorSerializer permission_classes = [IsAuthenticated] def create(self, request, *args, **kwargs): - serializer = CreateJuniorSerializer(context={"user":request.user,"first_name":request.data.get('first_name', ''), - "last_name": request.data.get('last_name',' ')}, data=request.data) + """Use CreateJuniorSerializer""" + serializer = CreateJuniorSerializer(context={"user":request.user, + "first_name":request.data.get('first_name', ''), + "last_name": request.data.get('last_name',' ')}, + data=request.data) if serializer.is_valid(): + """save serializer""" serializer.save() return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) class ValidateGuardianCode(viewsets.ViewSet): + """Check guardian code exist or not""" permission_classes = [IsAuthenticated] def list(self, request, *args, **kwargs): - guardian_code = request.data.get('guardian_code') + """check guardian code""" + guardian_code = self.request.GET.get('guardian_code').split(',') for code in guardian_code: guardian_data = Guardian.objects.filter(guardian_code=code).exists() if guardian_data: - return custom_response(SUCCESS_CODE['3028'], response_status=status.HTTP_200_OK) + return custom_response(SUCCESS_CODE['3013'], response_status=status.HTTP_200_OK) else: return custom_error_response(ERROR_CODE["2022"], response_status=status.HTTP_400_BAD_REQUEST) diff --git a/zod_bank/manage.py b/zod_bank/manage.py index 169c7c2..fe9e065 100755 --- a/zod_bank/manage.py +++ b/zod_bank/manage.py @@ -1,14 +1,18 @@ #!/usr/bin/env python """Django's command-line utility for administrative tasks.""" +"""Django import""" import os import sys def main(): + """Main function""" os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'zod_bank.settings') try: + """Import execute from command line function""" from django.core.management import execute_from_command_line except ImportError as exc: + """Show Exception error""" raise ImportError( "Couldn't import Django. Are you sure it's installed and " "available on your PYTHONPATH environment variable? Did you " diff --git a/zod_bank/requirements.txt b/zod_bank/requirements.txt index da73f65..a875fbf 100644 --- a/zod_bank/requirements.txt +++ b/zod_bank/requirements.txt @@ -33,6 +33,7 @@ django-timezone-field==5.1 djangorestframework==3.14.0 djangorestframework-simplejwt==5.2.2 drf-yasg==1.21.6 +gunicorn==20.1.0 inflection==0.5.1 jmespath==0.10.0 kombu==5.3.1 diff --git a/zod_bank/zod_bank/settings.py b/zod_bank/zod_bank/settings.py index 9e47b30..79eaeeb 100644 --- a/zod_bank/zod_bank/settings.py +++ b/zod_bank/zod_bank/settings.py @@ -57,7 +57,7 @@ INSTALLED_APPS = [ 'junior', 'guardian', ] -# CSRF_COOKIE_SECURE = False + MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', @@ -168,27 +168,9 @@ CORS_ALLOW_HEADERS = ( 'x-requested-with', ) -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/3.0/howto/static-files/ +"""Static files (CSS, JavaScript, Images) +https://docs.djangoproject.com/en/3.0/howto/static-files/""" -# -# MAIL_MAILER='smtp' -# MAIL_HOST='smtp.gmail.com' -# MAIL_PORT=587 -# mail_username='infozodbank@gmail.com' -# MAIL_PASSWORD='ghwdmznwwslvchga' -# MAIL_ENCRYPTION='tls' -# mail_from_address='infozodbank@gmail.com' -# MAIL_FROM_NAME="${APP_NAME}" - -# MAIL_MAILER='smtp' -# MAIL_HOST='smtp.gmail.com' -# MAIL_PORT=587 -# mail_username='ankita.jain@kiwitech.com' -# MAIL_PASSWORD='jaijain0912@' -# MAIL_ENCRYPTION='tls' -# mail_from_address='infozodbank@gmail.com' -# MAIL_FROM_NAME="${APP_NAME}" # Email settings EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' @@ -196,7 +178,7 @@ EMAIL_HOST = 'smtp.gmail.com' EMAIL_PORT = 587 EMAIL_USE_TLS = True EMAIL_HOST_USER = 'infozodbank@gmail.com' -EMAIL_HOST_PASSWORD = 'ghwdmznwwslvchga' # Replace with your Gmail email password or App password - +# Replace with your Gmail email password or App password +EMAIL_HOST_PASSWORD = 'ghwdmznwwslvchga' STATIC_URL = '/static/'