diff --git a/account/utils.py b/account/utils.py index 9aca671..d1e6e54 100644 --- a/account/utils.py +++ b/account/utils.py @@ -22,7 +22,7 @@ from junior.models import Junior from guardian.models import Guardian from account.models import UserDelete from base.messages import ERROR_CODE - +from django.utils import timezone # Define delete # user account condition, @@ -228,3 +228,4 @@ def generate_code(value, user_id): return code +OTP_EXPIRY = timezone.now() + timezone.timedelta(days=1) diff --git a/account/views.py b/account/views.py index c19cd4f..91ff650 100644 --- a/account/views.py +++ b/account/views.py @@ -22,7 +22,7 @@ from django.conf import settings """App Import""" from guardian.models import Guardian from junior.models import Junior -from guardian.utils import upload_image_to_alibaba +from guardian.utils import upload_image_to_alibaba, OTP_EXPIRY from account.models import UserDeviceDetails, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification from django.contrib.auth.models import User """Account serializer""" @@ -228,7 +228,7 @@ class ForgotPasswordAPIView(views.APIView): 'verification_code': verification_code } ) - expiry = timezone.now() + timezone.timedelta(days=1) + expiry = OTP_EXPIRY user_data, created = UserEmailOtp.objects.get_or_create(email=email) if created: user_data.expired_at = expiry @@ -399,7 +399,7 @@ class ReSendEmailOtp(viewsets.ModelViewSet): def create(self, request, *args, **kwargs): otp = generate_otp() if User.objects.filter(email=request.data['email']): - expiry = timezone.now() + timezone.timedelta(days=1) + expiry = OTP_EXPIRY email_data, created = UserEmailOtp.objects.get_or_create(email=request.data['email']) if created: email_data.expired_at = expiry diff --git a/base/messages.py b/base/messages.py index 74e4740..f803b54 100644 --- a/base/messages.py +++ b/base/messages.py @@ -76,14 +76,18 @@ ERROR_CODE = { "2043": "Article Survey with given id doesn't exist.", "2044": "Task does not exist", "2045": "Invalid guardian", + # past due date "2046": "Due date must be future date", # invalid junior id msg "2047": "Invalid Junior ID ", "2048": "Choose right file for image", + # task request "2049": "This task is already requested ", "2059": "Already exist junior", + # task status "2060": "Task does not exist or not in pending state", "2061": "Please insert image or check the image is valid or not." + } """Success message code""" SUCCESS_CODE = { diff --git a/guardian/serializers.py b/guardian/serializers.py index a8a2e46..f7016f5 100644 --- a/guardian/serializers.py +++ b/guardian/serializers.py @@ -215,6 +215,7 @@ class TaskDetailsSerializer(serializers.ModelSerializer): junior = JuniorDetailSerializer() remaining_time = serializers.SerializerMethodField('get_remaining_time') + is_expired = serializers.SerializerMethodField('get_is_expired') def get_remaining_time(self, obj): """ remaining time to complete task""" @@ -228,12 +229,16 @@ class TaskDetailsSerializer(serializers.ModelSerializer): return str(time_difference.days) + ' days ' + str(time_only) return str(NUMBER['zero']) + ' days ' + '00:00:00:00000' - + def get_is_expired(self, obj): + """ task expired or not""" + if obj.due_date < datetime.today().date(): + return True + return False class Meta(object): """Meta info""" model = JuniorTask fields = ['id', 'guardian', 'task_name', 'task_description', 'points', 'due_date','default_image', 'image', - 'requested_on', 'rejected_on', 'completed_on', + 'requested_on', 'rejected_on', 'completed_on', 'is_expired', 'junior', 'task_status', 'is_active', 'remaining_time', 'created_at','updated_at'] diff --git a/guardian/views.py b/guardian/views.py index 24cc345..5fe331e 100644 --- a/guardian/views.py +++ b/guardian/views.py @@ -1,6 +1,11 @@ """Views of Guardian""" # django imports +# Import IsAuthenticated +# Import viewsets and status +# Import PageNumberPagination +# Import User +# Import timezone from rest_framework.permissions import IsAuthenticated from rest_framework import viewsets, status from rest_framework.pagination import PageNumberPagination @@ -18,15 +23,15 @@ from django.utils import timezone # from utils file # Import account's serializer # Import account's task - +# Import notification constant +# Import send_notification function from .serializers import (UserSerializer, CreateGuardianSerializer, TaskSerializer, TaskDetailsSerializer, TopJuniorSerializer, ApproveJuniorSerializer, ApproveTaskSerializer) from .models import Guardian, JuniorTask from junior.models import Junior, JuniorPoints from account.models import UserEmailOtp, UserNotification from .tasks import generate_otp -from account.utils import send_otp_email -from account.utils import custom_response, custom_error_response +from account.utils import custom_response, custom_error_response, OTP_EXPIRY, send_otp_email from base.messages import ERROR_CODE, SUCCESS_CODE from base.constants import NUMBER from .utils import upload_image_to_alibaba @@ -58,13 +63,15 @@ class SignupViewset(viewsets.ModelViewSet): user = serializer.save() """Generate otp""" otp = generate_otp() - expiry = timezone.now() + timezone.timedelta(days=1) + # expire otp after 1 day + expiry = OTP_EXPIRY # 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""" send_otp_email(request.data['email'], otp) - send_notification(REGISTRATION, None, user.id, {}) + # send push notification for registration + send_notification.delay(REGISTRATION, None, user.id, {}) return custom_response(SUCCESS_CODE['3001'], response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) diff --git a/junior/models.py b/junior/models.py index 529e1e0..dc71c97 100644 --- a/junior/models.py +++ b/junior/models.py @@ -112,7 +112,8 @@ class JuniorPoints(models.Model): class JuniorGuardianRelationship(models.Model): """Junior Guardian relationship model""" - guardian = models.ForeignKey(Guardian, on_delete=models.CASCADE, related_name='guardian_relation', verbose_name='Guardian') + guardian = models.ForeignKey(Guardian, on_delete=models.CASCADE, related_name='guardian_relation', + verbose_name='Guardian') # associated junior with the task junior = models.ForeignKey(Junior, on_delete=models.CASCADE, related_name='junior_relation', verbose_name='Junior') # relation between guardian and junior""" diff --git a/junior/serializers.py b/junior/serializers.py index 3bc2540..13b6815 100644 --- a/junior/serializers.py +++ b/junior/serializers.py @@ -14,9 +14,9 @@ from guardian.tasks import generate_otp from base.messages import ERROR_CODE, SUCCESS_CODE from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER, JUN, ZOD from guardian.models import Guardian, JuniorTask -from account.models import UserEmailOtp +from account.models import UserEmailOtp, UserNotification from junior.utils import junior_notification_email, junior_approval_mail -from guardian.utils import real_time, update_referral_points +from guardian.utils import real_time, update_referral_points, convert_timedelta_into_datetime from notifications.utils import send_notification from notifications.constants import INVITED_GUARDIAN, APPROVED_JUNIOR @@ -393,6 +393,7 @@ class AddGuardianSerializer(serializers.ModelSerializer): instance.id), referral_code_used=junior_data.referral_code, is_verified=True) + UserNotification.objects.create(user=instance) return guardian_data else: user = User.objects.create(username=email, email=email, @@ -412,21 +413,36 @@ class AddGuardianSerializer(serializers.ModelSerializer): UserEmailOtp.objects.create(email=email, otp=otp_value, user_type=str(NUMBER['two']), expired_at=expiry_time, is_verified=True) + UserNotification.objects.create(user=user) JuniorGuardianRelationship.objects.create(guardian=guardian_data, junior=junior_data, relationship=relationship) + """Notification email""" junior_notification_email(email, full_name, email, password) junior_approval_mail(email, full_name) - send_notification(INVITED_GUARDIAN, None, junior_data.auth.id, {}) - send_notification(APPROVED_JUNIOR, None, email, {}) + send_notification.delay(INVITED_GUARDIAN, None, junior_data.auth.id, {}) + send_notification.delay(APPROVED_JUNIOR, None, guardian_data.user.id, {}) return guardian_data class StartTaskSerializer(serializers.ModelSerializer): """User task Serializer""" + task_duration = serializers.SerializerMethodField('get_task_duration') + + def get_task_duration(self, obj): + """ remaining time to complete task""" + due_date = datetime.combine(obj.due_date, datetime.max.time()) + # fetch real time + real_datetime = real_time() + # Perform the subtraction + if due_date > real_datetime: + time_difference = due_date - real_datetime + time_only = convert_timedelta_into_datetime(time_difference) + return str(time_difference.days) + ' days ' + str(time_only) + return str(NUMBER['zero']) + ' days ' + '00:00:00:00000' class Meta(object): """Meta class""" model = JuniorTask - fields = ('id', 'task_status') + fields = ('id', 'task_duration') def update(self, instance, validated_data): instance.task_status = str(NUMBER['two']) instance.save() diff --git a/junior/views.py b/junior/views.py index 1021bc8..7f3452a 100644 --- a/junior/views.py +++ b/junior/views.py @@ -20,6 +20,10 @@ import requests # Import account's serializer # Import account's task # import junior serializer +# Import update_positions_based_on_points +# Import upload_image_to_alibaba +# Import custom_response, custom_error_response +# Import constants from junior.models import Junior, JuniorPoints from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer,\ RemoveJuniorSerializer, CompleteTaskSerializer, JuniorPointsSerializer, @@ -43,7 +47,10 @@ from .utils import update_positions_based_on_points # approve junior API # create referral code # validation API - +# invite guardian API +# by junior +# Start task +# by junior API # Create your views here. class UpdateJuniorProfile(viewsets.ViewSet): """Update junior profile""" @@ -58,6 +65,7 @@ class UpdateJuniorProfile(viewsets.ViewSet): image = request.data.get('image') image_url = '' if image: + # check image size if image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) # convert into file @@ -91,6 +99,7 @@ class ValidateGuardianCode(viewsets.ViewSet): # fetch guardian object guardian_data = Guardian.objects.filter(guardian_code=code).exists() if guardian_data: + # successfully check guardian code 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) @@ -129,13 +138,13 @@ class AddJuniorAPIView(viewsets.ModelViewSet): def create(self, request, *args, **kwargs): """ junior list""" try: - info = {'user': request.user, 'email': request.data['email'], 'first_name': request.data['first_name'], - 'last_name': request.data['last_name'], 'relationship': str(request.data['relationship'])} + info_data = {'user': request.user, 'relationship': str(request.data['relationship']), 'email': request.data['email'], 'first_name': request.data['first_name'], + 'last_name': request.data['last_name']} if User.objects.filter(username=request.data['email']): return custom_error_response(ERROR_CODE['2059'], response_status=status.HTTP_400_BAD_REQUEST) # use AddJuniorSerializer serializer - serializer = AddJuniorSerializer(data=request.data, context=info) + serializer = AddJuniorSerializer(data=request.data, context=info_data) if serializer.is_valid(): # save serializer serializer.save() @@ -393,9 +402,10 @@ class StartTaskAPIView(views.APIView): if serializer.is_valid(): # save serializer serializer.save() - return custom_response(SUCCESS_CODE['3035'], None, response_status=status.HTTP_200_OK) + return custom_response(SUCCESS_CODE['3035'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) else: + # task in another state return custom_error_response(ERROR_CODE['2060'], response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)