Compare commits

..

4 Commits

24 changed files with 349 additions and 264 deletions

View File

@ -216,17 +216,10 @@ class GuardianSerializer(serializers.ModelSerializer):
def get_user_type(self, obj): def get_user_type(self, obj):
"""user type""" """user type"""
if self.context.get('user_type', ''): email_verified = UserEmailOtp.objects.filter(email=obj.user.username).last()
return self.context.get('user_type') if email_verified and email_verified.user_type is not None:
# remove the below code once user_type can be passed return email_verified.user_type
# from everywhere from where this serializer is being called return str(NUMBER['two'])
else:
email_verified = UserEmailOtp.objects.filter(
email=obj.user.username
).last()
if email_verified and email_verified.user_type is not None:
return email_verified.user_type
return str(NUMBER['two'])
def get_auth(self, obj): def get_auth(self, obj):
"""user email address""" """user email address"""

View File

@ -1,6 +1,4 @@
"""Account utils""" """Account utils"""
from celery import shared_task
"""Import django""" """Import django"""
from django.conf import settings from django.conf import settings
from rest_framework import viewsets, status from rest_framework import viewsets, status
@ -22,7 +20,7 @@ from rest_framework import serializers
# Import messages from base package""" # 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, UserDeviceDetails from account.models import UserDelete
from base.messages import ERROR_CODE from base.messages import ERROR_CODE
from django.utils import timezone from django.utils import timezone
from base.constants import NUMBER from base.constants import NUMBER
@ -46,7 +44,7 @@ from junior.models import JuniorPoints
# referral code, # referral code,
# Define function for generating # Define function for generating
# alphanumeric code # alphanumeric code
# otp expiry
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':
@ -111,7 +109,6 @@ def guardian_account_update(user_tb):
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()
@shared_task()
def send_otp_email(recipient_email, otp): 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
@ -127,20 +124,6 @@ def send_otp_email(recipient_email, otp):
) )
return otp return otp
@shared_task
def user_device_details(user, device_id):
"""
Used to store the device id of the user
user: user object
device_id: string
return
"""
device_details, created = UserDeviceDetails.objects.get_or_create(user=user)
if device_details:
device_details.device_id = device_id
device_details.save()
def send_support_email(name, sender, subject, message): 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]
@ -251,9 +234,3 @@ def generate_code(value, user_id):
OTP_EXPIRY = timezone.now() + timezone.timedelta(days=1) OTP_EXPIRY = timezone.now() + timezone.timedelta(days=1)
def get_user_full_name(user_obj):
"""
to get user's full name
"""
return f"{user_obj.first_name} {user_obj.last_name}" if user_obj.last_name else user_obj.first_name

View File

@ -1,12 +1,11 @@
"""Account view """ """Account view """
import threading
from notifications.utils import remove_fcm_token from notifications.utils import remove_fcm_token
# django imports # django imports
from datetime import datetime, timedelta from datetime import datetime, timedelta
from rest_framework import viewsets, status, views from rest_framework import viewsets, status, views
from rest_framework.decorators import action from rest_framework.decorators import action
import random
import logging import logging
from django.utils import timezone from django.utils import timezone
import jwt import jwt
@ -36,10 +35,10 @@ from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSeriali
AdminLoginSerializer) AdminLoginSerializer)
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, ZOD, JUN, GRD, USER_TYPE_FLAG 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,
generate_code, OTP_EXPIRY, user_device_details) generate_code, OTP_EXPIRY)
from junior.serializers import JuniorProfileSerializer from junior.serializers import JuniorProfileSerializer
from guardian.serializers import GuardianProfileSerializer from guardian.serializers import GuardianProfileSerializer
@ -281,48 +280,29 @@ class UserPhoneVerification(viewsets.ModelViewSet):
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)
class UserLogin(viewsets.ViewSet): class UserLogin(viewsets.ViewSet):
"""User login""" """User login"""
@action(methods=['post'], detail=False) @action(methods=['post'], detail=False)
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')
user_type = request.data.get('user_type')
device_id = request.META.get('HTTP_DEVICE_ID') device_id = request.META.get('HTTP_DEVICE_ID')
user = authenticate(request, username=username, password=password) user = authenticate(request, username=username, password=password)
try: try:
if user is not None: if user is not None:
login(request, user) login(request, user)
if str(user_type) == USER_TYPE_FLAG["TWO"]: guardian_data = Guardian.objects.filter(user__username=username, is_verified=True).last()
guardian_data = Guardian.objects.filter(user__username=username, is_verified=True).last() if guardian_data:
if guardian_data: serializer = GuardianSerializer(guardian_data).data
serializer = GuardianSerializer( junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last()
guardian_data, context={'user_type': user_type} if junior_data:
).data serializer = JuniorSerializer(junior_data).data
else: device_details, created = UserDeviceDetails.objects.get_or_create(user=user)
return custom_error_response( if device_details:
ERROR_CODE["2070"], device_details.device_id = device_id
response_status=status.HTTP_401_UNAUTHORIZED device_details.save()
)
elif str(user_type) == USER_TYPE_FLAG["FIRST"]:
junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last()
if junior_data:
serializer = JuniorSerializer(
junior_data, context={'user_type': user_type}
).data
else:
return custom_error_response(
ERROR_CODE["2071"],
response_status=status.HTTP_401_UNAUTHORIZED
)
else:
return custom_error_response(
ERROR_CODE["2069"],
response_status=status.HTTP_401_UNAUTHORIZED
)
# storing device id in using thread so the time would be reduced
threading.Thread(target=user_device_details, args=(user, device_id))
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)
@ -332,12 +312,9 @@ class UserLogin(viewsets.ViewSet):
refresh = RefreshToken.for_user(user) refresh = RefreshToken.for_user(user)
access_token = str(refresh.access_token) access_token = str(refresh.access_token)
refresh_token = str(refresh) refresh_token = str(refresh)
data = { data = {"auth_token":access_token, "refresh_token":refresh_token, "is_profile_complete": False,
"auth_token":access_token, "user_type": email_verified.user_type,
"refresh_token":refresh_token, }
"is_profile_complete": False,
"user_type": user_type,
}
is_verified = False is_verified = False
if email_verified: if email_verified:
is_verified = email_verified.is_verified is_verified = email_verified.is_verified
@ -346,18 +323,11 @@ class UserLogin(viewsets.ViewSet):
email_verified.otp = otp email_verified.otp = otp
email_verified.save() email_verified.save()
data.update({"email_otp":otp}) data.update({"email_otp":otp})
send_otp_email.delay(username, otp) send_otp_email(username, otp)
return custom_response( return custom_response(ERROR_CODE['2024'], {"email_otp": otp, "is_email_verified": is_verified},
ERROR_CODE['2024'], response_status=status.HTTP_200_OK)
{"email_otp": otp, "is_email_verified": is_verified},
response_status=status.HTTP_200_OK
)
data.update({"is_email_verified": is_verified}) data.update({"is_email_verified": is_verified})
return custom_response( return custom_response(SUCCESS_CODE['3003'], data, response_status=status.HTTP_200_OK)
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):
@ -401,13 +371,12 @@ class AdminLoginViewSet(viewsets.GenericViewSet):
class UserEmailVerification(viewsets.ModelViewSet): class UserEmailVerification(viewsets.ModelViewSet):
"""User Email verification""" """User Email verification"""
serializer_class = EmailVerificationSerializer serializer_class = EmailVerificationSerializer
http_method_names = ('post',)
def create(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
try: try:
user_obj = User.objects.filter(username=self.request.data.get('email')).last() user_obj = User.objects.filter(username=self.request.GET.get('email')).last()
email_data = UserEmailOtp.objects.filter(email=self.request.data.get('email'), email_data = UserEmailOtp.objects.filter(email=self.request.GET.get('email'),
otp=self.request.data.get('otp')).last() otp=self.request.GET.get('otp')).last()
if email_data: if email_data:
input_datetime_str = str(email_data.expired_at) input_datetime_str = str(email_data.expired_at)
input_format = "%Y-%m-%d %H:%M:%S.%f%z" input_format = "%Y-%m-%d %H:%M:%S.%f%z"
@ -421,12 +390,12 @@ class UserEmailVerification(viewsets.ModelViewSet):
email_data.is_verified = True email_data.is_verified = True
email_data.save() email_data.save()
if email_data.user_type == '1': if email_data.user_type == '1':
junior_data = Junior.objects.filter(auth__email=self.request.data.get('email')).last() junior_data = Junior.objects.filter(auth__email=self.request.GET.get('email')).last()
if junior_data: if junior_data:
junior_data.is_verified = True junior_data.is_verified = True
junior_data.save() junior_data.save()
else: else:
guardian_data = Guardian.objects.filter(user__email=self.request.data.get('email')).last() guardian_data = Guardian.objects.filter(user__email=self.request.GET.get('email')).last()
if guardian_data: if guardian_data:
guardian_data.is_verified = True guardian_data.is_verified = True
guardian_data.save() guardian_data.save()
@ -536,7 +505,7 @@ class UserNotificationAPIViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
"""profile view""" """profile view"""
queryset = UserNotification.objects.filter(user=request.user) queryset = self.queryset.filter(user=request.user)
serializer = UserNotificationSerializer(queryset, many=True) serializer = UserNotificationSerializer(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)

View File

@ -50,13 +50,6 @@ USER_TYPE = (
('2', 'guardian'), ('2', 'guardian'),
('3', 'superuser') ('3', 'superuser')
) )
USER_TYPE_FLAG = {
"FIRST" : "1",
"TWO" : "2",
"THREE": "3"
}
"""gender""" """gender"""
GENDERS = ( GENDERS = (
('1', 'Male'), ('1', 'Male'),

View File

@ -94,10 +94,7 @@ ERROR_CODE = {
"2065": "Passwords do not match. Please try again.", "2065": "Passwords do not match. Please try again.",
"2066": "Task does not exist or not in expired state", "2066": "Task does not exist or not in expired state",
"2067": "Action not allowed. User type missing.", "2067": "Action not allowed. User type missing.",
"2068": "No guardian associated with this junior", "2068": "No guardian associated with this junior"
"2069": "Invalid user type",
"2070": "You did not find as a guardian",
"2071": "You did not find as a junior"
} }
"""Success message code""" """Success message code"""

Binary file not shown.

View File

@ -29,7 +29,7 @@ from .utils import real_time, convert_timedelta_into_datetime, update_referral_p
# notification's constant # notification's constant
from notifications.constants import TASK_POINTS, TASK_REJECTED from notifications.constants import TASK_POINTS, TASK_REJECTED
# send notification function # send notification function
from notifications.utils import send_notification, send_notification_to_junior from notifications.utils import send_notification
# In this serializer file # In this serializer file
@ -383,8 +383,7 @@ class ApproveTaskSerializer(serializers.ModelSerializer):
# update complete time of task # update complete time of task
# instance.completed_on = real_time() # instance.completed_on = real_time()
instance.completed_on = timezone.now().astimezone(pytz.utc) instance.completed_on = timezone.now().astimezone(pytz.utc)
send_notification_to_junior.delay(TASK_POINTS, None, junior_details.auth.id, send_notification.delay(TASK_POINTS, None, junior_details.auth.id, {})
{'task_id': instance.id})
else: else:
# reject the task # reject the task
instance.task_status = str(NUMBER['three']) instance.task_status = str(NUMBER['three'])
@ -392,8 +391,7 @@ class ApproveTaskSerializer(serializers.ModelSerializer):
# update reject time of task # update reject time of task
# instance.rejected_on = real_time() # instance.rejected_on = real_time()
instance.rejected_on = timezone.now().astimezone(pytz.utc) instance.rejected_on = timezone.now().astimezone(pytz.utc)
send_notification_to_junior.delay(TASK_REJECTED, None, junior_details.auth.id, send_notification.delay(TASK_REJECTED, None, junior_details.auth.id, {})
{'task_id': instance.id})
instance.save() instance.save()
junior_data.save() junior_data.save()
return junior_details return junior_details

View File

@ -21,9 +21,7 @@ from zod_bank.celery import app
# notification's constant # notification's constant
from notifications.constants import REFERRAL_POINTS from notifications.constants import REFERRAL_POINTS
# send notification function # send notification function
from notifications.utils import send_notification, send_notification_to_junior from notifications.utils import send_notification
# Define upload image on # Define upload image on
# ali baba cloud # ali baba cloud
# firstly save image # firstly save image
@ -94,7 +92,7 @@ def update_referral_points(referral_code, referral_code_used):
junior_query.total_points = junior_query.total_points + NUMBER['five'] junior_query.total_points = junior_query.total_points + NUMBER['five']
junior_query.referral_points = junior_query.referral_points + NUMBER['five'] junior_query.referral_points = junior_query.referral_points + NUMBER['five']
junior_query.save() junior_query.save()
send_notification_to_junior.delay(REFERRAL_POINTS, None, junior_queryset.auth.id, {}) send_notification.delay(REFERRAL_POINTS, None, junior_queryset.auth.id, {})

View File

@ -38,8 +38,8 @@ from account.utils import custom_response, custom_error_response, OTP_EXPIRY, se
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import NUMBER, GUARDIAN_CODE_STATUS from base.constants import NUMBER, GUARDIAN_CODE_STATUS
from .utils import upload_image_to_alibaba from .utils import upload_image_to_alibaba
from notifications.constants import REGISTRATION, TASK_ASSIGNED, LEADERBOARD_RANKING from notifications.constants import REGISTRATION, TASK_CREATED, LEADERBOARD_RANKING
from notifications.utils import send_notification_to_junior from notifications.utils import send_notification
""" Define APIs """ """ Define APIs """
# Define Signup API, # Define Signup API,
@ -72,6 +72,8 @@ class SignupViewset(viewsets.ModelViewSet):
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"""
send_otp_email(request.data['email'], otp) send_otp_email(request.data['email'], otp)
# send push notification for registration
send_notification.delay(REGISTRATION, None, user.id, {})
return custom_response(SUCCESS_CODE['3001'], return custom_response(SUCCESS_CODE['3001'],
response_status=status.HTTP_200_OK) 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)
@ -184,10 +186,9 @@ class CreateTaskAPIView(viewsets.ModelViewSet):
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 # save serializer
task = serializer.save() serializer.save()
junior_id = Junior.objects.filter(id=junior).last() junior_id = Junior.objects.filter(id=junior).last()
send_notification_to_junior.delay(TASK_ASSIGNED, request.auth.payload['user_id'], send_notification.delay(TASK_CREATED, None, junior_id.auth.id, {})
junior_id.auth.id, {'task_id': task.id})
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)
except Exception as e: except Exception as e:
@ -240,7 +241,7 @@ class TopJuniorListAPIView(viewsets.ModelViewSet):
# Update the position field for each JuniorPoints object # Update the position field for each JuniorPoints object
for index, junior in enumerate(junior_total_points): for index, junior in enumerate(junior_total_points):
junior.position = index + 1 junior.position = index + 1
send_notification_to_junior.delay(LEADERBOARD_RANKING, None, junior.junior.auth.id, {}) send_notification.delay(LEADERBOARD_RANKING, None, junior.junior.auth.id, {})
junior.save() junior.save()
serializer = self.get_serializer(junior_total_points[:NUMBER['fifteen']], many=True) serializer = self.get_serializer(junior_total_points[:NUMBER['fifteen']], 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)

View File

@ -21,7 +21,7 @@ from guardian.models import Guardian, JuniorTask
from account.models import UserEmailOtp, UserNotification from account.models import UserEmailOtp, UserNotification
from junior.utils import junior_notification_email, junior_approval_mail from junior.utils import junior_notification_email, junior_approval_mail
from guardian.utils import real_time, update_referral_points, convert_timedelta_into_datetime from guardian.utils import real_time, update_referral_points, convert_timedelta_into_datetime
from notifications.utils import send_notification, send_notification_to_junior, send_notification_to_guardian from notifications.utils import send_notification
from notifications.constants import (INVITED_GUARDIAN, APPROVED_JUNIOR, SKIPPED_PROFILE_SETUP, TASK_ACTION, from notifications.constants import (INVITED_GUARDIAN, APPROVED_JUNIOR, SKIPPED_PROFILE_SETUP, TASK_ACTION,
TASK_SUBMITTED) TASK_SUBMITTED)
@ -98,7 +98,7 @@ class CreateJuniorSerializer(serializers.ModelSerializer):
JuniorGuardianRelationship.objects.get_or_create(guardian=guardian_data, junior=junior) JuniorGuardianRelationship.objects.get_or_create(guardian=guardian_data, junior=junior)
junior.guardian_code_status = str(NUMBER['three']) junior.guardian_code_status = str(NUMBER['three'])
junior_approval_mail(user.email, user.first_name) junior_approval_mail(user.email, user.first_name)
send_notification_to_guardian.delay(APPROVED_JUNIOR, junior.auth.id, guardian_data.user.id, {}) send_notification.delay(APPROVED_JUNIOR, None, guardian_data.user.id, {})
junior.dob = validated_data.get('dob', junior.dob) junior.dob = validated_data.get('dob', junior.dob)
junior.passcode = validated_data.get('passcode', junior.passcode) junior.passcode = validated_data.get('passcode', junior.passcode)
junior.country_name = validated_data.get('country_name', junior.country_name) junior.country_name = validated_data.get('country_name', junior.country_name)
@ -146,8 +146,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', 'image', 'is_invited', 'referral_code','is_active', 'is_complete_profile', 'guardian_code', 'image', 'is_invited', 'referral_code','is_active', 'is_complete_profile', 'created_at',
'created_at', 'image', 'updated_at'] 'image', 'updated_at']
class JuniorDetailListSerializer(serializers.ModelSerializer): class JuniorDetailListSerializer(serializers.ModelSerializer):
"""junior serializer""" """junior serializer"""
@ -305,7 +305,7 @@ class AddJuniorSerializer(serializers.ModelSerializer):
"""Notification email""" """Notification email"""
junior_notification_email(email, full_name, email, password) junior_notification_email(email, full_name, email, password)
# push notification # push notification
send_notification_to_junior.delay(SKIPPED_PROFILE_SETUP, None, junior_data.auth.id, {}) send_notification.delay(SKIPPED_PROFILE_SETUP, None, junior_data.auth.id, {})
return junior_data return junior_data
@ -320,7 +320,7 @@ class RemoveJuniorSerializer(serializers.ModelSerializer):
if instance: if instance:
instance.is_invited = False instance.is_invited = False
instance.guardian_code = '{}' instance.guardian_code = '{}'
instance.guardian_code_status = str(NUMBER['one']) instance.guardian_code_status = str(NUMBER['1'])
instance.save() instance.save()
return instance return instance
@ -337,10 +337,8 @@ class CompleteTaskSerializer(serializers.ModelSerializer):
instance.task_status = str(NUMBER['four']) instance.task_status = str(NUMBER['four'])
instance.is_approved = False instance.is_approved = False
instance.save() instance.save()
send_notification_to_junior.delay(TASK_SUBMITTED, instance.guardian.user.id, send_notification.delay(TASK_SUBMITTED, None, instance.junior.auth.id, {})
instance.junior.auth.id, {'task_id': instance.id}) send_notification.delay(TASK_ACTION, None, instance.guardian.user.id, {})
send_notification_to_guardian.delay(TASK_ACTION, instance.junior.auth.id,
instance.guardian.user.id, {'task_id': instance.id})
return instance return instance
class JuniorPointsSerializer(serializers.ModelSerializer): class JuniorPointsSerializer(serializers.ModelSerializer):
@ -450,8 +448,8 @@ class AddGuardianSerializer(serializers.ModelSerializer):
"""Notification email""" """Notification email"""
junior_notification_email(email, full_name, email, password) junior_notification_email(email, full_name, email, password)
junior_approval_mail(email, full_name) junior_approval_mail(email, full_name)
send_notification_to_junior.delay(INVITED_GUARDIAN, guardian_data.user.id, junior_data.auth.id, {}) send_notification.delay(INVITED_GUARDIAN, None, junior_data.auth.id, {})
send_notification_to_guardian.delay(APPROVED_JUNIOR, junior_data.auth.id, guardian_data.user.id, {}) send_notification.delay(APPROVED_JUNIOR, None, guardian_data.user.id, {})
return guardian_data return guardian_data
class StartTaskSerializer(serializers.ModelSerializer): class StartTaskSerializer(serializers.ModelSerializer):
@ -504,7 +502,6 @@ class RemoveGuardianCodeSerializer(serializers.ModelSerializer):
model = Junior model = Junior
fields = ('id', ) fields = ('id', )
def update(self, instance, validated_data): def update(self, instance, validated_data):
instance.guardian_code = None
instance.guardian_code_status = str(NUMBER['one']) instance.guardian_code_status = str(NUMBER['one'])
instance.save() instance.save()
return instance return instance

View File

@ -42,7 +42,7 @@ from base.constants import NUMBER, ARTICLE_STATUS
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
from .utils import update_positions_based_on_points from .utils import update_positions_based_on_points
from notifications.utils import send_notification, send_notification_to_junior from notifications.utils import send_notification
from notifications.constants import REMOVE_JUNIOR from notifications.constants import REMOVE_JUNIOR
from web_admin.models import Article, ArticleSurvey, SurveyOption, ArticleCard from web_admin.models import Article, ArticleSurvey, SurveyOption, ArticleCard
from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleListSerializer, from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleListSerializer,
@ -269,7 +269,7 @@ class RemoveJuniorAPIView(views.APIView):
if serializer.is_valid(): if serializer.is_valid():
# save serializer # save serializer
serializer.save() serializer.save()
send_notification_to_junior.delay(REMOVE_JUNIOR, None, junior_queryset.auth.id, {}) send_notification.delay(REMOVE_JUNIOR, None, junior_queryset.auth.id, {})
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)
else: else:
@ -334,8 +334,7 @@ class CompleteJuniorTaskAPIView(views.APIView):
image_url = upload_image_to_alibaba(image, filename) image_url = upload_image_to_alibaba(image, filename)
# fetch junior query # fetch junior query
task_queryset = JuniorTask.objects.filter(id=task_id, junior__auth__email=self.request.user task_queryset = JuniorTask.objects.filter(id=task_id, junior__auth__email=self.request.user).last()
).select_related('guardian', 'junior').last()
if task_queryset: if task_queryset:
# use CompleteTaskSerializer serializer # use CompleteTaskSerializer serializer
if task_queryset.task_status in [str(NUMBER['four']), str(NUMBER['five'])]: if task_queryset.task_status in [str(NUMBER['four']), str(NUMBER['five'])]:

View File

@ -3,7 +3,7 @@ notification constants file
""" """
from base.constants import NUMBER from base.constants import NUMBER
REGISTRATION = NUMBER['one'] REGISTRATION = NUMBER['one']
TASK_ASSIGNED = NUMBER['two'] TASK_CREATED = NUMBER['two']
INVITED_GUARDIAN = NUMBER['three'] INVITED_GUARDIAN = NUMBER['three']
APPROVED_JUNIOR = NUMBER['four'] APPROVED_JUNIOR = NUMBER['four']
REFERRAL_POINTS = NUMBER['five'] REFERRAL_POINTS = NUMBER['five']
@ -21,17 +21,17 @@ NOTIFICATION_DICT = {
"title": "Successfully registered!", "title": "Successfully registered!",
"body": "You have registered successfully. Now login and complete your profile." "body": "You have registered successfully. Now login and complete your profile."
}, },
TASK_ASSIGNED: { TASK_CREATED: {
"title": "New task assigned !!", "title": "Task created!",
"body": "{from_user} has assigned you a new task." "body": "Task created successfully."
}, },
INVITED_GUARDIAN: { INVITED_GUARDIAN: {
"title": "Invite guardian", "title": "Invite guardian",
"body": "Invite guardian successfully" "body": "Invite guardian successfully"
}, },
APPROVED_JUNIOR: { APPROVED_JUNIOR: {
"title": "Approve junior !", "title": "Approve junior",
"body": "You have request from {from_user} to associate with you." "body": "You have request from junior to associate with you"
}, },
REFERRAL_POINTS: { REFERRAL_POINTS: {
"title": "Earn Referral points", "title": "Earn Referral points",
@ -47,15 +47,15 @@ NOTIFICATION_DICT = {
}, },
SKIPPED_PROFILE_SETUP: { SKIPPED_PROFILE_SETUP: {
"title": "Skipped profile setup!", "title": "Skipped profile setup!",
"body": "Your guardian {from_user} has setup your profile." "body": "Your guardian has been setup your profile."
}, },
TASK_SUBMITTED: { TASK_SUBMITTED: {
"title": "Task submitted!", "title": "Task submitted!",
"body": "Your task has been submitted successfully." "body": "Your task has been submitted successfully."
}, },
TASK_ACTION: { TASK_ACTION: {
"title": "Task completion approval!", "title": "Task approval!",
"body": "You have request from {from_user} for task approval." "body": "You have request for task approval."
}, },
LEADERBOARD_RANKING: { LEADERBOARD_RANKING: {
"title": "Leader board rank!", "title": "Leader board rank!",
@ -67,6 +67,6 @@ NOTIFICATION_DICT = {
}, },
TEST_NOTIFICATION: { TEST_NOTIFICATION: {
"title": "Test Notification", "title": "Test Notification",
"body": "This notification is for testing purpose from {from_user}." "body": "This notification is for testing purpose"
} }
} }

View File

@ -35,8 +35,7 @@ class NotificationListSerializer(serializers.ModelSerializer):
class Meta(object): class Meta(object):
"""meta info""" """meta info"""
model = Notification model = Notification
fields = ['id', 'data', 'is_read', 'created_at'] fields = ['id', 'data', 'is_read']
class ReadNotificationSerializer(serializers.ModelSerializer): class ReadNotificationSerializer(serializers.ModelSerializer):
"""User task Serializer""" """User task Serializer"""

View File

@ -10,9 +10,6 @@ from firebase_admin.messaging import Message, Notification as FirebaseNotificati
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from account.models import UserNotification from account.models import UserNotification
from account.utils import get_user_full_name
from guardian.models import Guardian
from junior.models import Junior
from notifications.constants import NOTIFICATION_DICT from notifications.constants import NOTIFICATION_DICT
from notifications.models import Notification from notifications.models import Notification
@ -42,80 +39,30 @@ def remove_fcm_token(user_id: int, access_token: str, registration_id) -> None:
print(e) print(e)
def get_basic_detail(from_user_id, to_user_id): def get_basic_detail(notification_type, from_user_id, to_user_id):
""" """ used to get the basic details """
used to get the basic details notification_data = NOTIFICATION_DICT[notification_type]
"""
from_user = User.objects.get(id=from_user_id) if from_user_id else None from_user = User.objects.get(id=from_user_id) if from_user_id else None
to_user = User.objects.get(id=to_user_id) to_user = User.objects.get(id=to_user_id)
return from_user, to_user return notification_data, from_user, to_user
def get_notification_data(notification_type, from_user, to_user, extra_data): @shared_task()
""" def send_notification(notification_type, from_user_id, to_user_id, extra_data):
get notification and push data """ used to send the push for the given notification type """
:param notification_type: notification_type (notification_data, from_user, to_user) = get_basic_detail(notification_type, from_user_id, to_user_id)
:param from_user: from_user obj
:param to_user: to_user obj
:param extra_data: any extra data provided
:return: notification and push data
"""
push_data = NOTIFICATION_DICT[notification_type].copy()
notification_data = push_data.copy()
notification_data['to_user'] = get_user_full_name(to_user)
if from_user:
from_user_name = get_user_full_name(from_user)
push_data['body'] = push_data['body'].format(from_user=from_user_name)
notification_data['body'] = notification_data['body'].format(from_user=from_user_name)
notification_data['from_user'] = from_user_name
notification_data.update(extra_data)
return notification_data, push_data
def send_notification(notification_type, from_user, to_user, extra_data):
"""
used to send the push for the given notification type
"""
# (from_user, to_user) = get_basic_detail(from_user_id, to_user_id)
notification_data, push_data = get_notification_data(notification_type, from_user, to_user, extra_data)
user_notification_type = UserNotification.objects.filter(user=to_user).first() user_notification_type = UserNotification.objects.filter(user=to_user).first()
notification_data.update({'badge': Notification.objects.filter(notification_to=to_user, is_read=False).count()}) data = notification_data
Notification.objects.create(notification_type=notification_type, notification_from=from_user, Notification.objects.create(notification_type=notification_type, notification_from=from_user,
notification_to=to_user, data=notification_data) notification_to=to_user, data=data)
if user_notification_type.push_notification: if user_notification_type.push_notification:
send_push(to_user, push_data) data.update({'badge': Notification.objects.filter(notification_to=to_user, is_read=False).count()})
send_push(to_user, data)
def send_push(user, data): def send_push(user, data):
""" used to send push notification to specific user """ """ used to send push notification to specific user """
notification_data = data.pop('data', None)
user.fcmdevice_set.filter(active=True).send_message( user.fcmdevice_set.filter(active=True).send_message(
Message(notification=FirebaseNotification(data['title'], data['body']), data=data) Message(notification=FirebaseNotification(data['title'], data['body']), data=notification_data)
) )
@shared_task()
def send_notification_to_guardian(notification_type, from_user_id, to_user_id, extra_data):
from_user = None
if from_user_id:
from_user = Junior.objects.filter(auth_id=from_user_id).select_related('auth').first()
extra_data['from_user_image'] = from_user.image
from_user = from_user.auth
to_user = Guardian.objects.filter(user_id=to_user_id).select_related('user').first()
extra_data['to_user_image'] = to_user.image
send_notification(notification_type, from_user, to_user.user, extra_data)
@shared_task()
def send_notification_to_junior(notification_type, from_user_id, to_user_id, extra_data):
from_user = None
if from_user_id:
from_user = Guardian.objects.filter(user_id=from_user_id).select_related('user').first()
extra_data['from_user_image'] = from_user.image
from_user = from_user.user
to_user = Junior.objects.filter(auth_id=to_user_id).select_related('auth').first()
extra_data['to_user_image'] = to_user.image
send_notification(notification_type, from_user, to_user.auth, extra_data)

View File

@ -11,10 +11,8 @@ from rest_framework import viewsets, status, views
from account.utils import custom_response, custom_error_response from account.utils import custom_response, custom_error_response
from base.messages import SUCCESS_CODE, ERROR_CODE from base.messages import SUCCESS_CODE, ERROR_CODE
from notifications.constants import TEST_NOTIFICATION from notifications.constants import TEST_NOTIFICATION
# Import serializer
from notifications.serializers import RegisterDevice, NotificationListSerializer, ReadNotificationSerializer from notifications.serializers import RegisterDevice, NotificationListSerializer, ReadNotificationSerializer
from notifications.utils import send_notification, send_notification_to_guardian, send_notification_to_junior from notifications.utils import send_notification
# Import model
from notifications.models import Notification from notifications.models import Notification
@ -56,10 +54,7 @@ class NotificationViewSet(viewsets.GenericViewSet):
to send test notification to send test notification
:return: :return:
""" """
send_notification_to_guardian(TEST_NOTIFICATION, None, request.auth.payload['user_id'], send_notification.delay(TEST_NOTIFICATION, None, request.auth.payload['user_id'], {})
{'task_id': None})
send_notification_to_junior(TEST_NOTIFICATION, request.auth.payload['user_id'], None,
{'task_id': None})
return custom_response(SUCCESS_CODE["3000"]) return custom_response(SUCCESS_CODE["3000"])
@action(methods=['get'], detail=False, url_path='list', url_name='list', @action(methods=['get'], detail=False, url_path='list', url_name='list',

View File

@ -99,3 +99,6 @@ uritemplate==4.1.1
urllib3==1.26.16 urllib3==1.26.16
vine==5.0.0 vine==5.0.0
wcwidth==0.2.6 wcwidth==0.2.6
pandas==2.0.3
XlsxWriter==3.1.2

View File

@ -1,13 +1,18 @@
""" """
web_admin pagination file web_admin pagination file
""" """
# third party imports
from rest_framework.pagination import PageNumberPagination from rest_framework.pagination import PageNumberPagination
from base.constants import NUMBER
class CustomPageNumberPagination(PageNumberPagination): class CustomPageNumberPagination(PageNumberPagination):
""" """
custom paginator class custom paginator class
""" """
page_size = 10 # Set the desired page size # Set the desired page size
page_size = NUMBER['ten']
page_size_query_param = 'page_size' page_size_query_param = 'page_size'
max_page_size = 100 # Set a maximum page size if needed # Set a maximum page size if needed
max_page_size = NUMBER['hundred']

View File

@ -1,12 +1,24 @@
""" """
web_admin analytics serializer file web_admin analytics serializer file
""" """
# third party imports
from rest_framework import serializers from rest_framework import serializers
# django imports
from django.contrib.auth import get_user_model
# local imports
from base.constants import USER_TYPE
from junior.models import JuniorPoints, Junior from junior.models import JuniorPoints, Junior
USER = get_user_model()
class JuniorLeaderboardSerializer(serializers.ModelSerializer): class JuniorLeaderboardSerializer(serializers.ModelSerializer):
"""
junior leaderboard serializer
"""
name = serializers.SerializerMethodField() name = serializers.SerializerMethodField()
first_name = serializers.SerializerMethodField() first_name = serializers.SerializerMethodField()
last_name = serializers.SerializerMethodField() last_name = serializers.SerializerMethodField()
@ -44,9 +56,75 @@ class JuniorLeaderboardSerializer(serializers.ModelSerializer):
class LeaderboardSerializer(serializers.ModelSerializer): class LeaderboardSerializer(serializers.ModelSerializer):
"""
leaderboard serializer
"""
junior = JuniorLeaderboardSerializer() junior = JuniorLeaderboardSerializer()
rank = serializers.IntegerField() rank = serializers.IntegerField()
class Meta: class Meta:
"""
meta class
"""
model = JuniorPoints model = JuniorPoints
fields = ('total_points', 'rank', 'junior') fields = ('total_points', 'rank', 'junior')
class UserCSVReportSerializer(serializers.ModelSerializer):
"""
user csv/xls report serializer
"""
phone_number = serializers.SerializerMethodField()
user_type = serializers.SerializerMethodField()
is_active = serializers.SerializerMethodField()
date_joined = serializers.SerializerMethodField()
class Meta:
"""
meta class
"""
model = USER
fields = ('first_name', 'last_name', 'email', 'phone_number', 'user_type', 'is_active', 'date_joined')
@staticmethod
def get_phone_number(obj):
"""
:param obj: user object
:return: user phone number
"""
if profile := (obj.guardian_profile.all().first() or obj.junior_profile.all().first()):
return f"+{profile.country_code}{profile.phone}" \
if profile.country_code and profile.phone else profile.phone
else:
return None
@staticmethod
def get_user_type(obj):
"""
:param obj: user object
:return: user type
"""
if obj.guardian_profile.all().first():
return dict(USER_TYPE).get('2').capitalize()
elif obj.junior_profile.all().first():
return dict(USER_TYPE).get('1').capitalize()
else:
return None
@staticmethod
def get_is_active(obj):
"""
:param obj: user object
:return: user type
"""
if profile := (obj.guardian_profile.all().first() or obj.junior_profile.all().first()):
return "Active" if profile.is_active else "Inactive"
@staticmethod
def get_date_joined(obj):
"""
:param obj: user obj
:return: formatted date
"""
date = obj.date_joined.strftime("%d %b %Y")
return date

View File

@ -224,7 +224,7 @@ class ArticleListSerializer(serializers.ModelSerializer):
total_points = serializers.SerializerMethodField('get_total_points') total_points = serializers.SerializerMethodField('get_total_points')
is_completed = serializers.SerializerMethodField('get_is_completed') is_completed = serializers.SerializerMethodField('get_is_completed')
class Meta(object): class Meta:
""" """
meta class meta class
""" """
@ -238,8 +238,7 @@ class ArticleListSerializer(serializers.ModelSerializer):
def get_is_completed(self, obj): def get_is_completed(self, obj):
"""complete all question""" """complete all question"""
context_data = self.context.get('user') junior_article = JuniorArticle.objects.filter(article=obj).last()
junior_article = JuniorArticle.objects.filter(junior__auth=context_data, article=obj).last()
if junior_article: if junior_article:
return junior_article.is_completed return junior_article.is_completed
return False return False
@ -279,7 +278,7 @@ class ArticleQuestionSerializer(serializers.ModelSerializer):
return junior_article_obj.submitted_answer.id return junior_article_obj.submitted_answer.id
return None return None
class Meta(object): class Meta:
""" """
meta class meta class
""" """
@ -300,7 +299,7 @@ class StartAssessmentSerializer(serializers.ModelSerializer):
if data: if data:
return data.current_que_page return data.current_que_page
return NUMBER['zero'] return NUMBER['zero']
class Meta(object): class Meta:
""" """
meta class meta class
""" """
@ -326,7 +325,7 @@ class ArticleCardlistSerializer(serializers.ModelSerializer):
return data.current_card_page return data.current_card_page
return NUMBER['zero'] return NUMBER['zero']
class Meta(object): class Meta:
""" """
meta class meta class
""" """

View File

@ -5,7 +5,7 @@ web_admin user_management serializers file
from rest_framework import serializers from rest_framework import serializers
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from base.constants import USER_TYPE from base.constants import USER_TYPE, GUARDIAN, JUNIOR
# local imports # local imports
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from guardian.models import Guardian from guardian.models import Guardian
@ -210,10 +210,10 @@ class JuniorSerializer(serializers.ModelSerializer):
""" """
instance.auth.email = self.validated_data.get('email', instance.auth.email) instance.auth.email = self.validated_data.get('email', instance.auth.email)
instance.auth.username = self.validated_data.get('email', instance.auth.username) instance.auth.username = self.validated_data.get('email', instance.auth.username)
instance.auth.save() instance.auth.save(update_fields=['email', 'username'])
instance.country_code = validated_data.get('country_code', instance.country_code) instance.country_code = validated_data.get('country_code', instance.country_code)
instance.phone = validated_data.get('phone', instance.phone) instance.phone = validated_data.get('phone', instance.phone)
instance.save() instance.save(update_fields=['country_code', 'phone'])
return instance return instance
@staticmethod @staticmethod
@ -265,33 +265,30 @@ class UserManagementDetailSerializer(serializers.ModelSerializer):
model = USER model = USER
fields = ('id', 'user_type', 'email', 'guardian_profile', 'junior_profile', 'associated_users') fields = ('id', 'user_type', 'email', 'guardian_profile', 'junior_profile', 'associated_users')
@staticmethod def get_user_type(self, obj):
def get_user_type(obj):
""" """
:param obj: user object :param obj: user object
:return: user type :return: user type
""" """
if obj.guardian_profile.all().first(): return GUARDIAN if self.context['user_type'] == GUARDIAN else JUNIOR
return dict(USER_TYPE).get('2')
elif obj.junior_profile.all().first():
return dict(USER_TYPE).get('1')
else:
return None
@staticmethod def get_associated_users(self, obj):
def get_associated_users(obj):
""" """
:param obj: user object :param obj: user object
:return: associated user :return: associated user
""" """
if profile := obj.guardian_profile.all().first(): if self.context['user_type'] == GUARDIAN:
profile = obj.guardian_profile.all().only('user_id', 'guardian_code').first()
if profile.guardian_code: if profile.guardian_code:
junior = Junior.objects.filter(guardian_code__contains=[profile.guardian_code], is_verified=True) junior = Junior.objects.filter(guardian_code__contains=[profile.guardian_code],
is_verified=True).select_related('auth')
serializer = JuniorSerializer(junior, many=True) serializer = JuniorSerializer(junior, many=True)
return serializer.data return serializer.data
elif profile := obj.junior_profile.all().first(): elif self.context['user_type'] == JUNIOR:
profile = obj.junior_profile.all().only('auth_id', 'guardian_code').first()
if profile.guardian_code: if profile.guardian_code:
guardian = Guardian.objects.filter(guardian_code__in=profile.guardian_code, is_verified=True) guardian = Guardian.objects.filter(guardian_code__in=profile.guardian_code,
is_verified=True).select_related('user')
serializer = GuardianSerializer(guardian, many=True) serializer = GuardianSerializer(guardian, many=True)
return serializer.data return serializer.data
else: else:

View File

@ -3,6 +3,12 @@ web_admin analytics view file
""" """
# python imports # python imports
import datetime import datetime
import io
import pandas as pd
import xlsxwriter
import tempfile
import oss2
from django.conf import settings
# third party imports # third party imports
from rest_framework.viewsets import GenericViewSet from rest_framework.viewsets import GenericViewSet
@ -16,15 +22,17 @@ from django.db.models import Count
from django.db.models.functions import TruncDate from django.db.models.functions import TruncDate
from django.db.models import F, Window from django.db.models import F, Window
from django.db.models.functions.window import Rank from django.db.models.functions.window import Rank
from django.http import HttpResponse
# local imports # local imports
from account.utils import custom_response from account.utils import custom_response
from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, EXPIRED, DATE_FORMAT from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, EXPIRED, DATE_FORMAT, TASK_STATUS
from guardian.models import JuniorTask from guardian.models import JuniorTask
from junior.models import JuniorPoints from junior.models import JuniorPoints
from web_admin.pagination import CustomPageNumberPagination from web_admin.pagination import CustomPageNumberPagination
from web_admin.permission import AdminPermission from web_admin.permission import AdminPermission
from web_admin.serializers.analytics_serializer import LeaderboardSerializer from web_admin.serializers.analytics_serializer import LeaderboardSerializer, UserCSVReportSerializer
from web_admin.serializers.user_management_serializer import UserManagementListSerializer
USER = get_user_model() USER = get_user_model()
@ -141,3 +149,121 @@ class AnalyticsViewSet(GenericViewSet):
paginated_queryset = paginator.paginate_queryset(queryset, request) paginated_queryset = paginator.paginate_queryset(queryset, request)
serializer = self.serializer_class(paginated_queryset, many=True) serializer = self.serializer_class(paginated_queryset, many=True)
return custom_response(None, serializer.data) return custom_response(None, serializer.data)
@action(methods=['get'], url_name='export-excel', url_path='export-excel', detail=False)
def export_excel(self, request):
"""
to export users count, task details and top juniors in csv/excel file
:param request: start_date: date format (yyyy-mm-dd)
:param request: end_date: date format (yyyy-mm-dd)
:return:
"""
response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = 'attachment; filename="ZOD_Bank_Analytics.xlsx"'
end_date = datetime.date.today()
start_date = end_date - datetime.timedelta(days=6)
if request.query_params.get('start_date') and request.query_params.get('end_date'):
start_date = datetime.datetime.strptime(request.query_params.get('start_date'), DATE_FORMAT)
end_date = datetime.datetime.strptime(request.query_params.get('end_date'), DATE_FORMAT)
# Use BytesIO for binary data
buffer = io.BytesIO()
# Create an XlsxWriter Workbook object
workbook = xlsxwriter.Workbook(buffer)
# Add sheets
sheets = ['Users', 'Assign Tasks', 'Juniors leaderboard']
for sheet_name in sheets:
worksheet = workbook.add_worksheet(name=sheet_name)
# sheet 1 for Total Users
if sheet_name == 'Users':
user_qs = self.get_queryset()
queryset = user_qs.filter(date_joined__range=(start_date, (end_date + datetime.timedelta(days=1))))
serializer = UserCSVReportSerializer(queryset, many=True)
df_users = pd.DataFrame([
{'Name': f"{user['first_name']} {user['last_name']}",
'Email': user['email'], 'Phone Number': user['phone_number'],
'User Type': user['user_type'], 'Status': user['is_active'],
'Date Joined': user['date_joined']}
for user in serializer.data
])
for idx, col in enumerate(df_users.columns):
# Write header
worksheet.write(0, idx, col)
for row_num, row in enumerate(df_users.values, start=1):
for col_num, value in enumerate(row):
worksheet.write(row_num, col_num, value)
# sheet 2 for Assign Task
elif sheet_name == 'Assign Tasks':
assign_tasks = JuniorTask.objects.filter(
created_at__range=[start_date, (end_date + datetime.timedelta(days=1))]
).exclude(task_status__in=[PENDING, EXPIRED])
df_tasks = pd.DataFrame([
{'Task Name': task.task_name, 'Task Status': dict(TASK_STATUS).get(task.task_status).capitalize()}
for task in assign_tasks
])
for idx, col in enumerate(df_tasks.columns):
# Write header
worksheet.write(0, idx, col)
for row_num, row in enumerate(df_tasks.values, start=1):
for col_num, value in enumerate(row):
worksheet.write(row_num, col_num, value)
# sheet 3 for Juniors Leaderboard and rank
elif sheet_name == 'Juniors leaderboard':
queryset = JuniorPoints.objects.prefetch_related('junior', 'junior__auth').annotate(rank=Window(
expression=Rank(),
order_by=[F('total_points').desc(), 'junior__created_at']
)).order_by('-total_points', 'junior__created_at')
df_leaderboard = pd.DataFrame([
{
'Junior Name': f"{junior.junior.auth.first_name} {junior.junior.auth.last_name}"
if junior.junior.auth.last_name else junior.junior.auth.first_name,
'Points': junior.total_points,
'Rank': junior.rank
}
for junior in queryset
])
for idx, col in enumerate(df_leaderboard.columns):
# Write header
worksheet.write(0, idx, col)
for row_num, row in enumerate(df_leaderboard.values, start=1):
for col_num, value in enumerate(row):
worksheet.write(row_num, col_num, value)
# Close the workbook to save the content
workbook.close()
# Reset the buffer position and write the content to the response
buffer.seek(0)
response.write(buffer.getvalue())
buffer.close()
filename = f"{'analytics'}/{'ZOD_Bank_Analytics.xlsx'}"
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
"""write image in temporary file"""
temp_file.write(response.content)
"""auth of bucket"""
auth = oss2.Auth(settings.ALIYUN_OSS_ACCESS_KEY_ID, settings.ALIYUN_OSS_ACCESS_KEY_SECRET)
"""fetch bucket details"""
bucket = oss2.Bucket(auth, settings.ALIYUN_OSS_ENDPOINT, settings.ALIYUN_OSS_BUCKET_NAME)
# Upload the temporary file to Alibaba OSS
bucket.put_object_from_file(filename, temp_file.name)
"""create perfect url for image"""
new_filename = filename.replace(' ', '%20')
link = f"https://{settings.ALIYUN_OSS_BUCKET_NAME}.{settings.ALIYUN_OSS_ENDPOINT}/{new_filename}"
print(link)
return custom_response(None, link)

View File

@ -221,7 +221,10 @@ class ArticleListViewSet(GenericViewSet, mixins.ListModelMixin):
:return: list of article :return: list of article
""" """
queryset = self.get_queryset() queryset = self.get_queryset()
serializer = self.serializer_class(queryset, context={"user": request.user}, many=True) count = queryset.count()
paginator = self.pagination_class()
paginated_queryset = paginator.paginate_queryset(queryset, request)
serializer = self.serializer_class(paginated_queryset, many=True)
return custom_response(None, data=serializer.data) return custom_response(None, data=serializer.data)
class ArticleCardListViewSet(viewsets.ModelViewSet): class ArticleCardListViewSet(viewsets.ModelViewSet):

View File

@ -14,6 +14,8 @@ from django.db.models import Q
from account.utils import custom_response, custom_error_response from account.utils import custom_response, custom_error_response
from base.constants import USER_TYPE from base.constants import USER_TYPE
from base.messages import SUCCESS_CODE, ERROR_CODE from base.messages import SUCCESS_CODE, ERROR_CODE
from guardian.models import Guardian
from junior.models import Junior
from web_admin.permission import AdminPermission from web_admin.permission import AdminPermission
from web_admin.serializers.user_management_serializer import (UserManagementListSerializer, from web_admin.serializers.user_management_serializer import (UserManagementListSerializer,
UserManagementDetailSerializer, GuardianSerializer, UserManagementDetailSerializer, GuardianSerializer,
@ -70,12 +72,14 @@ class UserManagementViewSet(GenericViewSet, mixins.ListModelMixin,
""" """
if self.request.query_params.get('user_type') not in [dict(USER_TYPE).get('1'), dict(USER_TYPE).get('2')]: if self.request.query_params.get('user_type') not in [dict(USER_TYPE).get('1'), dict(USER_TYPE).get('2')]:
return custom_error_response(ERROR_CODE['2067'], status.HTTP_400_BAD_REQUEST) return custom_error_response(ERROR_CODE['2067'], status.HTTP_400_BAD_REQUEST)
queryset = self.queryset queryset = self.queryset
if self.request.query_params.get('user_type') == dict(USER_TYPE).get('2'): queryset = queryset.filter(id=kwargs['pk'])
queryset = queryset.filter(guardian_profile__user__id=kwargs['pk'])
elif self.request.query_params.get('user_type') == dict(USER_TYPE).get('1'): serializer = UserManagementDetailSerializer(
queryset = queryset.filter(junior_profile__auth__id=kwargs['pk']) queryset, many=True,
serializer = UserManagementDetailSerializer(queryset, many=True) context={'user_type': self.request.query_params.get('user_type')}
)
return custom_response(None, data=serializer.data) return custom_response(None, data=serializer.data)
def partial_update(self, request, *args, **kwargs): def partial_update(self, request, *args, **kwargs):
@ -87,15 +91,14 @@ class UserManagementViewSet(GenericViewSet, mixins.ListModelMixin,
""" """
if self.request.query_params.get('user_type') not in [dict(USER_TYPE).get('1'), dict(USER_TYPE).get('2')]: if self.request.query_params.get('user_type') not in [dict(USER_TYPE).get('1'), dict(USER_TYPE).get('2')]:
return custom_error_response(ERROR_CODE['2067'], status.HTTP_400_BAD_REQUEST) return custom_error_response(ERROR_CODE['2067'], status.HTTP_400_BAD_REQUEST)
queryset = self.queryset
if self.request.query_params.get('user_type') == dict(USER_TYPE).get('2'): if self.request.query_params.get('user_type') == dict(USER_TYPE).get('2'):
user_obj = queryset.filter(guardian_profile__user__id=kwargs['pk']).first() guardian = Guardian.objects.filter(user_id=kwargs['pk'], is_verified=True).first()
serializer = GuardianSerializer(user_obj.guardian_profile.all().first(), serializer = GuardianSerializer(guardian,
request.data, context={'user_id': kwargs['pk']}) request.data, context={'user_id': kwargs['pk']})
elif self.request.query_params.get('user_type') == dict(USER_TYPE).get('1'): elif self.request.query_params.get('user_type') == dict(USER_TYPE).get('1'):
user_obj = queryset.filter(junior_profile__auth__id=kwargs['pk']).first() junior = Junior.objects.filter(auth_id=kwargs['pk'], is_verified=True).select_related('auth').first()
serializer = JuniorSerializer(user_obj.junior_profile.all().first(), serializer = JuniorSerializer(junior,
request.data, context={'user_id': kwargs['pk']}) request.data, context={'user_id': kwargs['pk']})
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
@ -114,12 +117,12 @@ class UserManagementViewSet(GenericViewSet, mixins.ListModelMixin,
return custom_error_response(ERROR_CODE['2067'], status.HTTP_400_BAD_REQUEST) return custom_error_response(ERROR_CODE['2067'], status.HTTP_400_BAD_REQUEST)
queryset = self.queryset queryset = self.queryset
if self.request.query_params.get('user_type') == dict(USER_TYPE).get('2'): if self.request.query_params.get('user_type') == dict(USER_TYPE).get('2'):
user_obj = queryset.filter(guardian_profile__user__id=kwargs['pk']).first() user_obj = queryset.filter(id=kwargs['pk']).first()
obj = user_obj.guardian_profile.all().first() obj = user_obj.guardian_profile.all().first()
obj.is_active = False if obj.is_active else True obj.is_active = False if obj.is_active else True
obj.save() obj.save()
elif self.request.query_params.get('user_type') == dict(USER_TYPE).get('1'): elif self.request.query_params.get('user_type') == dict(USER_TYPE).get('1'):
user_obj = queryset.filter(junior_profile__auth__id=kwargs['pk']).first() user_obj = queryset.filter(id=kwargs['pk']).first()
obj = user_obj.junior_profile.all().first() obj = user_obj.junior_profile.all().first()
obj.is_active = False if obj.is_active else True obj.is_active = False if obj.is_active else True
obj.save() obj.save()

View File

@ -125,6 +125,7 @@ SIMPLE_JWT = {
# Database # Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases # https://docs.djangoproject.com/en/3.0/ref/settings/#databases
DATABASES = { DATABASES = {
# default db setting
'default': { 'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis', 'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME':os.getenv('DB_NAME'), 'NAME':os.getenv('DB_NAME'),
@ -177,6 +178,9 @@ AUTH_PASSWORD_VALIDATORS = [
}, },
] ]
# database query logs settings
# Allows us to check db hits
# useful to optimize db query and hit
LOGGING = { LOGGING = {
"version": 1, "version": 1,
"filters": { "filters": {
@ -193,6 +197,7 @@ LOGGING = {
"class": "logging.StreamHandler" "class": "logging.StreamHandler"
} }
}, },
# database logger
"loggers": { "loggers": {
"django.db.backends": { "django.db.backends": {
"level": "DEBUG", "level": "DEBUG",
@ -242,6 +247,7 @@ CORS_ALLOW_HEADERS = (
'x-requested-with', 'x-requested-with',
) )
# CORS header settings
CORS_EXPOSE_HEADERS = ( CORS_EXPOSE_HEADERS = (
'Access-Control-Allow-Origin: *', 'Access-Control-Allow-Origin: *',
) )
@ -297,5 +303,7 @@ STATIC_URL = 'static/'
# define static root # define static root
STATIC_ROOT = 'static' STATIC_ROOT = 'static'
# media url
MEDIA_URL = "/media/" MEDIA_URL = "/media/"
# media path
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'media') MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'media')