modified top-list api, junior-list api and junior-points api, nodified rank method, added mail for deactivating user from admin

This commit is contained in:
abutalib-kiwi
2023-08-24 19:34:59 +05:30
parent 1a2fd2d3a8
commit 2e0ceb8c92
11 changed files with 94 additions and 71 deletions

View File

@ -0,0 +1,22 @@
{% extends "templated_email/email_base.email" %}
{% block subject %}
Account Deactivated
{% endblock %}
{% block plain %}
<tr>
<td style="padding: 0 27px 15px;">
<p style="margin: 0; font-size: 16px; line-height: 20px; padding: 36px 0 0; font-weight: 500; color: #1f2532;">
Hi User,
</p>
</td>
</tr>
<tr>
<td style="padding: 0 27px 22px;">
<p style="margin: 0;font-size: 14px; font-weight: 400; line-height: 21px; color: #1f2532;">
Your account has been deactivated by admin. Please reach out to the admin for assistance.
</p>
</td>
</tr>
{% endblock %}

View File

@ -18,27 +18,7 @@ from notifications.utils import send_notification
@shared_task @shared_task
def send_email_otp(email, verification_code): def send_email(recipient_list, template, context: dict = None):
"""
used to send otp on email
:param email: e-mail
:param verification_code: otp
"""
from_email = settings.EMAIL_FROM_ADDRESS
recipient_list = [email]
send_templated_mail(
template_name='email_reset_verification.email',
from_email=from_email,
recipient_list=recipient_list,
context={
'verification_code': verification_code
}
)
return True
@shared_task
def send_mail(recipient_list, template, context: dict = None):
""" """
used to send otp on email used to send otp on email
:param context: :param context:
@ -48,7 +28,6 @@ def send_mail(recipient_list, template, context: dict = None):
if context is None: if context is None:
context = {} context = {}
from_email = settings.EMAIL_FROM_ADDRESS from_email = settings.EMAIL_FROM_ADDRESS
recipient_list = recipient_list
send_templated_mail( send_templated_mail(
template_name=template, template_name=template,
from_email=from_email, from_email=from_email,

Binary file not shown.

View File

@ -316,10 +316,11 @@ class TaskDetailsjuniorSerializer(serializers.ModelSerializer):
'requested_on', 'rejected_on', 'completed_on', 'requested_on', 'rejected_on', 'completed_on',
'junior', 'task_status', 'is_active', 'remaining_time', 'created_at','updated_at'] 'junior', 'task_status', 'is_active', 'remaining_time', 'created_at','updated_at']
class TopJuniorSerializer(serializers.ModelSerializer): class TopJuniorSerializer(serializers.ModelSerializer):
"""Top junior serializer""" """Top junior serializer"""
junior = JuniorDetailSerializer() junior = JuniorDetailSerializer()
position = serializers.IntegerField() position = serializers.SerializerMethodField()
class Meta(object): class Meta(object):
"""Meta info""" """Meta info"""
@ -329,9 +330,13 @@ class TopJuniorSerializer(serializers.ModelSerializer):
def to_representation(self, instance): def to_representation(self, instance):
"""Convert instance to representation""" """Convert instance to representation"""
representation = super().to_representation(instance) representation = super().to_representation(instance)
representation['position'] = instance.position
return representation return representation
@staticmethod
def get_position(obj):
""" get position/rank """
return obj.rank
class GuardianProfileSerializer(serializers.ModelSerializer): class GuardianProfileSerializer(serializers.ModelSerializer):
"""junior serializer""" """junior serializer"""

View File

@ -6,6 +6,8 @@
# Import PageNumberPagination # Import PageNumberPagination
# Import User # Import User
# Import timezone # Import timezone
from django.db.models import F, Window
from django.db.models.functions.window import Rank
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework import viewsets, status from rest_framework import viewsets, status
from rest_framework.pagination import PageNumberPagination from rest_framework.pagination import PageNumberPagination
@ -242,7 +244,6 @@ class SearchTaskListAPIView(viewsets.ModelViewSet):
class TopJuniorListAPIView(viewsets.ModelViewSet): class TopJuniorListAPIView(viewsets.ModelViewSet):
"""Top juniors list """Top juniors list
No Params""" No Params"""
queryset = JuniorPoints.objects.all()
serializer_class = TopJuniorSerializer serializer_class = TopJuniorSerializer
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
http_method_names = ('get',) http_method_names = ('get',)
@ -253,15 +254,18 @@ class TopJuniorListAPIView(viewsets.ModelViewSet):
context.update({'view': self}) context.update({'view': self})
return context return context
def get_queryset(self):
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')
return queryset
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
"""Fetch junior list of those who complete their tasks""" """Fetch junior list of those who complete their tasks"""
try: try:
junior_total_points = self.get_queryset().order_by('-total_points') junior_total_points = self.get_queryset()[:15]
# Update the position field for each JuniorPoints object serializer = self.get_serializer(junior_total_points, many=True)
for index, junior in enumerate(junior_total_points):
junior.position = index + 1
junior.save()
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)
except Exception as e: except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)

View File

@ -19,7 +19,7 @@ from base.constants import (PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED
GUARDIAN_CODE_STATUS, JUNIOR) GUARDIAN_CODE_STATUS, JUNIOR)
from guardian.models import Guardian, JuniorTask 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, get_junior_leaderboard_rank
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 from notifications.utils import send_notification
from notifications.constants import (ASSOCIATE_REQUEST, JUNIOR_ADDED, TASK_ACTION, from notifications.constants import (ASSOCIATE_REQUEST, JUNIOR_ADDED, TASK_ACTION,
@ -185,9 +185,8 @@ class JuniorDetailListSerializer(serializers.ModelSerializer):
return data return data
def get_position(self, obj): def get_position(self, obj):
data = JuniorPoints.objects.filter(junior=obj).last() return get_junior_leaderboard_rank(obj)
if data:
return data.position
def get_points(self, obj): def get_points(self, obj):
data = JuniorPoints.objects.filter(junior=obj).last() data = JuniorPoints.objects.filter(junior=obj).last()
if data: if data:
@ -365,10 +364,7 @@ class JuniorPointsSerializer(serializers.ModelSerializer):
return obj.junior.id return obj.junior.id
def get_position(self, obj): def get_position(self, obj):
data = JuniorPoints.objects.filter(junior=obj.junior).last() return get_junior_leaderboard_rank(obj.junior)
if data:
return data.position
return 99999
def get_points(self, obj): def get_points(self, obj):
"""total points""" """total points"""
points = JuniorPoints.objects.filter(junior=obj.junior).last() points = JuniorPoints.objects.filter(junior=obj.junior).last()

View File

@ -5,7 +5,8 @@ from django.conf import settings
from templated_email import send_templated_mail from templated_email import send_templated_mail
from .models import JuniorPoints from .models import JuniorPoints
from base.constants import NUMBER from base.constants import NUMBER
from django.db.models import F from django.db.models import F, Window
from django.db.models.functions.window import Rank
# junior notification # junior notification
# email for sending email # email for sending email
# when guardian create junior profile # when guardian create junior profile
@ -61,3 +62,19 @@ def update_positions_based_on_points():
junior_point.position = position junior_point.position = position
junior_point.save() junior_point.save()
position += NUMBER['one'] position += NUMBER['one']
def get_junior_leaderboard_rank(junior_obj):
"""
to get junior's position/rank
:param junior_obj:
:return: junior's position/rank
"""
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')
junior = next((query for query in queryset if query.junior == junior_obj), None)
return junior.rank if junior else None

View File

@ -142,7 +142,7 @@ class JuniorListAPIView(viewsets.ModelViewSet):
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
""" junior list""" """ junior list"""
try: try:
update_positions_based_on_points() # update_positions_based_on_points, function removed
guardian_data = Guardian.objects.filter(user__email=request.user).last() guardian_data = Guardian.objects.filter(user__email=request.user).last()
# fetch junior object # fetch junior object
if guardian_data: if guardian_data:
@ -417,7 +417,7 @@ class JuniorPointsListAPIView(viewsets.ModelViewSet):
"""Junior Points """Junior Points
No Params""" No Params"""
try: try:
update_positions_based_on_points() # update_positions_based_on_points, function removed
queryset = JuniorPoints.objects.filter(junior__auth__email=self.request.user).last() queryset = JuniorPoints.objects.filter(junior__auth__email=self.request.user).last()
# update position of junior # update position of junior
serializer = JuniorPointsSerializer(queryset) serializer = JuniorPointsSerializer(queryset)

View File

@ -14,7 +14,7 @@ from account.models import UserEmailOtp
from base.constants import USER_TYPE from base.constants import USER_TYPE
from base.messages import ERROR_CODE from base.messages import ERROR_CODE
from guardian.tasks import generate_otp from guardian.tasks import generate_otp
from base.tasks import send_mail from base.tasks import send_email
USER = get_user_model() USER = get_user_model()
@ -54,7 +54,7 @@ class AdminOTPSerializer(serializers.ModelSerializer):
data = { data = {
"verification_code": verification_code "verification_code": verification_code
} }
send_mail.delay([email], template, data) send_email.delay([email], template, data)
expiry = timezone.now() + timezone.timedelta(days=1) expiry = timezone.now() + timezone.timedelta(days=1)
user_data, created = UserEmailOtp.objects.update_or_create(email=email, user_data, created = UserEmailOtp.objects.update_or_create(email=email,

View File

@ -12,8 +12,9 @@ from django.db.models import Q
# local imports # local imports
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, GUARDIAN, JUNIOR
from base.messages import SUCCESS_CODE, ERROR_CODE from base.messages import SUCCESS_CODE, ERROR_CODE
from base.tasks import send_email
from guardian.models import Guardian from guardian.models import Guardian
from junior.models import Junior from junior.models import Junior
from web_admin.permission import AdminPermission from web_admin.permission import AdminPermission
@ -92,12 +93,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)
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'):
guardian = Guardian.objects.filter(user_id=kwargs['pk'], is_verified=True).first() guardian = Guardian.objects.filter(user_id=kwargs['pk'], is_verified=True
).select_related('user').first()
serializer = GuardianSerializer(guardian, 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'):
junior = Junior.objects.filter(auth_id=kwargs['pk'], is_verified=True).select_related('auth').first() junior = Junior.objects.filter(auth_id=kwargs['pk'], is_verified=True
).select_related('auth').first()
serializer = JuniorSerializer(junior, serializer = JuniorSerializer(junior,
request.data, context={'user_id': kwargs['pk']}) request.data, context={'user_id': kwargs['pk']})
@ -113,17 +116,21 @@ class UserManagementViewSet(GenericViewSet, mixins.ListModelMixin,
user_type {'guardian' for Guardian, 'junior' for Junior} mandatory user_type {'guardian' for Guardian, 'junior' for Junior} mandatory
:return: success message :return: success message
""" """
if self.request.query_params.get('user_type') not in [dict(USER_TYPE).get('1'), dict(USER_TYPE).get('2')]: user_type = self.request.query_params.get('user_type')
if user_type not in [GUARDIAN, JUNIOR]:
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'): email_template = 'user_deactivate.email'
user_obj = queryset.filter(id=kwargs['pk']).first()
obj = user_obj.guardian_profile.all().first() if user_type == GUARDIAN:
obj.is_active = False if obj.is_active else True obj = Guardian.objects.filter(user_id=kwargs['pk'], is_verified=True).select_related('user').first()
obj.save() elif user_type == JUNIOR:
elif self.request.query_params.get('user_type') == dict(USER_TYPE).get('1'): obj = Junior.objects.filter(auth_id=kwargs['pk'], is_verified=True).select_related('auth').first()
user_obj = queryset.filter(id=kwargs['pk']).first()
obj = user_obj.junior_profile.all().first() if obj.is_active:
obj.is_active = False if obj.is_active else True obj.is_active = False
obj.save() send_email([obj.user.email if user_type == GUARDIAN else obj.auth.email], email_template)
else:
obj.is_active = True
obj.save()
return custom_response(SUCCESS_CODE['3038']) return custom_response(SUCCESS_CODE['3038'])

View File

@ -28,9 +28,13 @@ app.config_from_object('django.conf:settings')
app.autodiscover_tasks() app.autodiscover_tasks()
app.conf.beat_schedule = { app.conf.beat_schedule = {
"expired_task": {
"task": "guardian.utils.update_expired_task_status",
"schedule": crontab(minute=0, hour=0),
},
'notify_task_expiry': { 'notify_task_expiry': {
'task': 'base.tasks.notify_task_expiry', 'task': 'base.tasks.notify_task_expiry',
'schedule': crontab(minute='0', hour='*/1'), 'schedule': crontab(minute='30', hour='19'),
}, },
} }
@ -39,14 +43,3 @@ app.conf.beat_schedule = {
def debug_task(self): def debug_task(self):
""" celery debug task """ """ celery debug task """
print(f'Request: {self.request!r}') print(f'Request: {self.request!r}')
"""cron task"""
app.conf.beat_schedule = {
"expired_task": {
"task": "guardian.utils.update_expired_task_status",
"schedule": crontab(minute=0, hour=0),
},
}