mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2026-10-23 09:37:56 +00:00
Compare commits
72
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65d0932893 | ||
|
|
9b14eedb18 | ||
|
|
116fb00358 | ||
|
|
20fa6e43da | ||
|
|
7b75a3233c | ||
|
|
4f79a690c1 | ||
|
|
0af2a35206 | ||
|
|
d24f075110 | ||
|
|
dc12b35842 | ||
|
|
3ad29e677d | ||
|
|
8b0a5d9a8e | ||
|
|
d4008d6cc2 | ||
|
|
a8d291474a | ||
|
|
e6482167ae | ||
|
|
9a932d31b5 | ||
|
|
e2c84eb83d | ||
|
|
5bfc3966b3 | ||
|
|
37d191eef8 | ||
|
|
e9ee8ec8b2 | ||
|
|
cc5ecc0647 | ||
|
|
63dfd731fc | ||
|
|
e9d4d7091e | ||
|
|
219bae792e | ||
|
|
df3cab99a5 | ||
|
|
d2242d4c64 | ||
|
|
b7d5916f8e | ||
|
|
5e17edcf3f | ||
|
|
b6fe943bfc | ||
|
|
8e529b292d | ||
|
|
61ca2e7d2d | ||
|
|
966f94eb1e | ||
|
|
f424c99478 | ||
|
|
34359360e0 | ||
|
|
685a822e52 | ||
|
|
e57344e54f | ||
|
|
235fc9baac | ||
|
|
3dc8268b07 | ||
|
|
8be8d56036 | ||
|
|
c79a891c89 | ||
|
|
eb4e09964d | ||
|
|
cf9376663c | ||
|
|
9891060ee3 | ||
|
|
5b2ab2275e | ||
|
|
9b6a84c7d1 | ||
|
|
e9d4fbe373 | ||
|
|
21b92f8c74 | ||
|
|
c46b2ef52c | ||
|
|
c47f6222d9 | ||
|
|
b82902081f | ||
|
|
e9315beab9 | ||
|
|
3a938720dd | ||
|
|
464899f7d3 | ||
|
|
8a436bb79f | ||
|
|
2e0ceb8c92 | ||
|
|
1a2fd2d3a8 | ||
|
|
a65eb2f77d | ||
|
|
3d06139c4f | ||
|
|
f5a03e2fdf | ||
|
|
226ddfa7e6 | ||
|
|
1028822908 | ||
|
|
342f27fc62 | ||
|
|
e9aa2dfda9 | ||
|
|
624e7a4edb | ||
|
|
339c49577e | ||
|
|
09f006eb13 | ||
|
|
ab1a2be679 | ||
|
|
11605540d7 | ||
|
|
8cd4864748 | ||
|
|
ad0b5bfc75 | ||
|
|
b1b7c42438 | ||
|
|
8f9450b743 | ||
|
|
bb3441e4ed |
@@ -17,6 +17,8 @@ from guardian.models import Guardian
|
|||||||
# multiple devices only
|
# multiple devices only
|
||||||
# user can login in single
|
# user can login in single
|
||||||
# device at a time"""
|
# device at a time"""
|
||||||
|
# force update
|
||||||
|
# use 308 status code for force update
|
||||||
|
|
||||||
def custom_response(custom_error, response_status = status.HTTP_404_NOT_FOUND):
|
def custom_response(custom_error, response_status = status.HTTP_404_NOT_FOUND):
|
||||||
"""custom response"""
|
"""custom response"""
|
||||||
@@ -43,9 +45,14 @@ class CustomMiddleware(object):
|
|||||||
device_type = str(request.META.get('HTTP_TYPE'))
|
device_type = str(request.META.get('HTTP_TYPE'))
|
||||||
|
|
||||||
api_endpoint = request.path
|
api_endpoint = request.path
|
||||||
|
unrestricted_api = ('/api/v1/user/login/', '/api/v1/logout/', '/api/v1/generate-token/')
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
# device details
|
# device details
|
||||||
device_details = UserDeviceDetails.objects.filter(user=request.user, device_id=device_id).last()
|
if device_id:
|
||||||
|
device_details = UserDeviceDetails.objects.filter(user=request.user, device_id=device_id).last()
|
||||||
|
if not device_details and api_endpoint not in unrestricted_api:
|
||||||
|
custom_error = custom_error_response(ERROR_CODE['2037'], response_status=status.HTTP_404_NOT_FOUND)
|
||||||
|
response = custom_response(custom_error)
|
||||||
if user_type and str(user_type) == str(NUMBER['one']):
|
if user_type and str(user_type) == str(NUMBER['one']):
|
||||||
junior = Junior.objects.filter(auth=request.user, is_active=False).last()
|
junior = Junior.objects.filter(auth=request.user, is_active=False).last()
|
||||||
if junior:
|
if junior:
|
||||||
@@ -56,13 +63,11 @@ class CustomMiddleware(object):
|
|||||||
if guardian:
|
if guardian:
|
||||||
custom_error = custom_error_response(ERROR_CODE['2075'], response_status=status.HTTP_404_NOT_FOUND)
|
custom_error = custom_error_response(ERROR_CODE['2075'], response_status=status.HTTP_404_NOT_FOUND)
|
||||||
response = custom_response(custom_error)
|
response = custom_response(custom_error)
|
||||||
if device_id and not device_details and api_endpoint != '/api/v1/user/login/':
|
|
||||||
custom_error = custom_error_response(ERROR_CODE['2037'], response_status=status.HTTP_404_NOT_FOUND)
|
if version and device_type:
|
||||||
response = custom_response(custom_error)
|
force_update = ForceUpdate.objects.filter(version=version, device_type=device_type).last()
|
||||||
force_update = ForceUpdate.objects.filter(version=version, device_type=device_type).last()
|
if not force_update:
|
||||||
api_endpoint_checks = not any(endpoint in api_endpoint for endpoint in ['/admin/', '/api/v1/admin/'])
|
custom_error = custom_error_response(ERROR_CODE['2079'],
|
||||||
if not force_update and version and device_type:
|
response_status=status.HTTP_308_PERMANENT_REDIRECT)
|
||||||
custom_error = custom_error_response(ERROR_CODE['2079'],
|
response = custom_response(custom_error, status.HTTP_308_PERMANENT_REDIRECT)
|
||||||
response_status=status.HTTP_308_PERMANENT_REDIRECT)
|
|
||||||
response = custom_response(custom_error, status.HTTP_308_PERMANENT_REDIRECT)
|
|
||||||
return response
|
return response
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ class ChangePasswordSerializer(serializers.Serializer):
|
|||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
"""
|
"""
|
||||||
|
change password
|
||||||
"""
|
"""
|
||||||
new_password = validated_data.pop('new_password')
|
new_password = validated_data.pop('new_password')
|
||||||
current_password = validated_data.pop('current_password')
|
current_password = validated_data.pop('current_password')
|
||||||
@@ -392,7 +392,8 @@ class UserPhoneOtpSerializer(serializers.ModelSerializer):
|
|||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
class ForceUpdateSerializer(serializers.ModelSerializer):
|
class ForceUpdateSerializer(serializers.ModelSerializer):
|
||||||
# ForceUpdate Serializer
|
""" ForceUpdate Serializer
|
||||||
|
"""
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
""" meta info """
|
""" meta info """
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{% extends "templated_email/email_base.email" %}
|
{% extends "templated_email/email_base.email" %}
|
||||||
|
|
||||||
{% block subject %}
|
{% block subject %}
|
||||||
{{subject}}
|
Support Mail
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block plain %}
|
{% block plain %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
+40
-7
@@ -1,6 +1,6 @@
|
|||||||
"""Account utils"""
|
"""Account utils"""
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
|
import random
|
||||||
"""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
|
||||||
@@ -93,8 +93,8 @@ def junior_account_update(user_tb):
|
|||||||
# Update junior account
|
# Update junior account
|
||||||
junior_data.is_active = False
|
junior_data.is_active = False
|
||||||
junior_data.is_verified = False
|
junior_data.is_verified = False
|
||||||
junior_data.guardian_code = '{}'
|
junior_data.guardian_code = None
|
||||||
junior_data.guardian_code_status = str(NUMBER['one'])
|
junior_data.guardian_code_status = None
|
||||||
junior_data.is_deleted = True
|
junior_data.is_deleted = True
|
||||||
junior_data.save()
|
junior_data.save()
|
||||||
JuniorPoints.objects.filter(junior=junior_data).delete()
|
JuniorPoints.objects.filter(junior=junior_data).delete()
|
||||||
@@ -167,7 +167,7 @@ def user_device_details(user, device_id):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def send_support_email(name, sender, subject, message):
|
def send_support_email(name, sender, 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]
|
||||||
from_email = settings.DEFAULT_ADDRESS
|
from_email = settings.DEFAULT_ADDRESS
|
||||||
@@ -179,19 +179,19 @@ def send_support_email(name, sender, subject, message):
|
|||||||
context={
|
context={
|
||||||
'name': name.title(),
|
'name': name.title(),
|
||||||
'sender': sender,
|
'sender': sender,
|
||||||
'subject': subject,
|
|
||||||
'message': message
|
'message': message
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
def custom_response(detail, data=None, response_status=status.HTTP_200_OK, count=None):
|
def custom_response(detail, data=None, total_pages=None, current_page=None, response_status=status.HTTP_200_OK, count=None):
|
||||||
"""Custom response code"""
|
"""Custom response code"""
|
||||||
if not data:
|
if not data:
|
||||||
"""when data is none"""
|
"""when data is none"""
|
||||||
data = None
|
data = None
|
||||||
return Response({"data": data, "message": detail, "status": "success", "code": response_status, "count": count})
|
return Response({"data": data, "message": detail, "total_pages":total_pages, "current_page":current_page,
|
||||||
|
"status": "success", "code": response_status, "count": count})
|
||||||
|
|
||||||
|
|
||||||
def custom_error_response(detail, response_status):
|
def custom_error_response(detail, response_status):
|
||||||
@@ -288,3 +288,36 @@ def get_user_full_name(user_obj):
|
|||||||
to get user's full name
|
to get user's full name
|
||||||
"""
|
"""
|
||||||
return f"{user_obj.first_name} {user_obj.last_name}" if user_obj.first_name or user_obj.last_name else "User"
|
return f"{user_obj.first_name} {user_obj.last_name}" if user_obj.first_name or user_obj.last_name else "User"
|
||||||
|
|
||||||
|
def make_special_password(length=10):
|
||||||
|
# Define character sets
|
||||||
|
lowercase_letters = string.ascii_lowercase
|
||||||
|
uppercase_letters = string.ascii_uppercase
|
||||||
|
digits = string.digits
|
||||||
|
special_characters = '!@#$%^&*()_-+=<>?/[]{}|'
|
||||||
|
|
||||||
|
# Combine character sets
|
||||||
|
all_characters = lowercase_letters + uppercase_letters + digits + special_characters
|
||||||
|
|
||||||
|
# Create a password with random characters
|
||||||
|
password = (
|
||||||
|
random.choice(lowercase_letters) +
|
||||||
|
random.choice(uppercase_letters) +
|
||||||
|
random.choice(digits) +
|
||||||
|
random.choice(special_characters) +
|
||||||
|
''.join(random.choice(all_characters) for _ in range(length - 4))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Shuffle the characters to make it more random
|
||||||
|
password_list = list(password)
|
||||||
|
random.shuffle(password_list)
|
||||||
|
return ''.join(password_list)
|
||||||
|
|
||||||
|
def task_status_fun(status_value):
|
||||||
|
"""task status"""
|
||||||
|
task_status_value = ['1']
|
||||||
|
if str(status_value) == '2':
|
||||||
|
task_status_value = ['2', '4']
|
||||||
|
elif str(status_value) == '3':
|
||||||
|
task_status_value = ['3', '5', '6']
|
||||||
|
return task_status_value
|
||||||
|
|||||||
+3
-5
@@ -322,7 +322,7 @@ class ForgotPasswordAPIView(views.APIView):
|
|||||||
send_all_email.delay(
|
send_all_email.delay(
|
||||||
'email_reset_verification.email', email, verification_code
|
'email_reset_verification.email', email, verification_code
|
||||||
)
|
)
|
||||||
expiry = OTP_EXPIRY
|
expiry = timezone.now() + timezone.timedelta(days=1)
|
||||||
user_data, created = UserEmailOtp.objects.get_or_create(
|
user_data, created = UserEmailOtp.objects.get_or_create(
|
||||||
email=email
|
email=email
|
||||||
)
|
)
|
||||||
@@ -546,7 +546,6 @@ class UserEmailVerification(viewsets.ModelViewSet):
|
|||||||
class ReSendEmailOtp(viewsets.ModelViewSet):
|
class ReSendEmailOtp(viewsets.ModelViewSet):
|
||||||
"""Send otp on phone"""
|
"""Send otp on phone"""
|
||||||
serializer_class = EmailVerificationSerializer
|
serializer_class = EmailVerificationSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
|
||||||
http_method_names = ('post',)
|
http_method_names = ('post',)
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
"""Param
|
"""Param
|
||||||
@@ -690,11 +689,10 @@ class SendSupportEmail(views.APIView):
|
|||||||
def post(self, request):
|
def post(self, request):
|
||||||
name = request.data.get('name')
|
name = request.data.get('name')
|
||||||
sender = request.data.get('email')
|
sender = request.data.get('email')
|
||||||
subject = request.data.get('subject')
|
|
||||||
message = request.data.get('message')
|
message = request.data.get('message')
|
||||||
if name and sender and subject and message:
|
if name and sender and message:
|
||||||
try:
|
try:
|
||||||
send_support_email(name, sender, subject, message)
|
send_support_email(name, sender, message)
|
||||||
return custom_response(SUCCESS_CODE['3019'], response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3019'], 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)
|
||||||
|
|||||||
+2
-1
@@ -43,7 +43,8 @@ FILE_SIZE = 5 * 1024 * 1024
|
|||||||
|
|
||||||
# String constant for configurable date for allocation lock period
|
# String constant for configurable date for allocation lock period
|
||||||
ALLOCATION_LOCK_DATE = 1
|
ALLOCATION_LOCK_DATE = 1
|
||||||
|
# guardian code status tuple
|
||||||
|
guardian_code_tuple = ('1','3')
|
||||||
"""user type"""
|
"""user type"""
|
||||||
USER_TYPE = (
|
USER_TYPE = (
|
||||||
('1', 'junior'),
|
('1', 'junior'),
|
||||||
|
|||||||
+11
-3
@@ -101,12 +101,20 @@ ERROR_CODE = {
|
|||||||
"2072": "You can not approve or reject this task because junior does not exist in the system",
|
"2072": "You can not approve or reject this task because junior does not exist in the system",
|
||||||
"2073": "You can not approve or reject this junior because junior does not exist in the system",
|
"2073": "You can not approve or reject this junior because junior does not exist in the system",
|
||||||
"2074": "You can not complete this task because you does not exist in the system",
|
"2074": "You can not complete this task because you does not exist in the system",
|
||||||
|
# deactivate account
|
||||||
"2075": "Your account is deactivated. Please contact with admin",
|
"2075": "Your account is deactivated. Please contact with admin",
|
||||||
"2076": "This junior already associate with you",
|
"2076": "This junior already associate with you",
|
||||||
"2077": "You can not add guardian",
|
"2077": "You can not add guardian",
|
||||||
"2078": "This junior is not associate with you",
|
"2078": "This junior is not associate with you",
|
||||||
|
# force update
|
||||||
"2079": "Please update your app version for enjoying uninterrupted services",
|
"2079": "Please update your app version for enjoying uninterrupted services",
|
||||||
"2080": "Can not add App version"
|
"2080": "Can not add App version",
|
||||||
|
"2081": "A junior can only be associated with a maximum of 3 guardian",
|
||||||
|
# guardian code not exist
|
||||||
|
"2082": "Guardian code does not exist",
|
||||||
|
"2083": "You can not start this task because guardian is not associate with you",
|
||||||
|
"2084": "You can not complete this task because guardian is not associate with you",
|
||||||
|
"2085": "You can not take action on this task because junior is not associate with you"
|
||||||
|
|
||||||
}
|
}
|
||||||
"""Success message code"""
|
"""Success message code"""
|
||||||
@@ -142,8 +150,8 @@ SUCCESS_CODE = {
|
|||||||
"3018": "Task created successfully",
|
"3018": "Task created successfully",
|
||||||
"3019": "Support Email sent successfully",
|
"3019": "Support Email sent successfully",
|
||||||
"3020": "Logged out successfully.",
|
"3020": "Logged out successfully.",
|
||||||
"3021": "Add junior successfully",
|
"3021": "Added junior successfully",
|
||||||
"3022": "Remove junior successfully",
|
"3022": "Removed junior successfully",
|
||||||
"3023": "Junior is approved successfully",
|
"3023": "Junior is approved successfully",
|
||||||
"3024": "Junior request is rejected successfully",
|
"3024": "Junior request is rejected successfully",
|
||||||
"3025": "Task is approved successfully",
|
"3025": "Task is approved successfully",
|
||||||
|
|||||||
+33
-24
@@ -9,36 +9,20 @@ from templated_email import send_templated_mail
|
|||||||
|
|
||||||
# django imports
|
# django imports
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.db.models import F, Window
|
||||||
|
from django.db.models.functions.window import Rank
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from base.constants import PENDING, IN_PROGRESS, JUNIOR
|
from base.constants import PENDING, IN_PROGRESS, JUNIOR
|
||||||
from guardian.models import JuniorTask
|
from guardian.models import JuniorTask
|
||||||
from notifications.constants import PENDING_TASK_EXPIRING, IN_PROGRESS_TASK_EXPIRING
|
from junior.models import JuniorPoints
|
||||||
from notifications.utils import send_notification
|
from notifications.constants import PENDING_TASK_EXPIRING, IN_PROGRESS_TASK_EXPIRING, NOTIFICATION_DICT, TOP_JUNIOR
|
||||||
|
from notifications.models import Notification
|
||||||
|
from notifications.utils import send_notification, get_from_user_details, send_notification_multiple_user
|
||||||
|
|
||||||
|
|
||||||
@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 +32,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,
|
||||||
@@ -77,3 +60,29 @@ def notify_task_expiry():
|
|||||||
send_notification(IN_PROGRESS_TASK_EXPIRING, task.junior.auth.id, JUNIOR, task.guardian.user.id,
|
send_notification(IN_PROGRESS_TASK_EXPIRING, task.junior.auth.id, JUNIOR, task.guardian.user.id,
|
||||||
{'task_id': task.id})
|
{'task_id': task.id})
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task()
|
||||||
|
def notify_top_junior():
|
||||||
|
"""
|
||||||
|
task to send notification for top leaderboard junior to all junior's
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
junior_points_qs = JuniorPoints.objects.filter(
|
||||||
|
junior__is_verified=True
|
||||||
|
).select_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')
|
||||||
|
|
||||||
|
prev_top_position = junior_points_qs.filter(position=1).first()
|
||||||
|
new_top_position = junior_points_qs.filter(rank=1).first()
|
||||||
|
if prev_top_position != new_top_position:
|
||||||
|
send_notification_multiple_user(TOP_JUNIOR, new_top_position.junior.auth.id, JUNIOR,
|
||||||
|
{'points': new_top_position.total_points})
|
||||||
|
for junior_point in junior_points_qs:
|
||||||
|
junior_point.position = junior_point.rank
|
||||||
|
junior_point.save()
|
||||||
|
return True
|
||||||
|
|||||||
Binary file not shown.
+35
-10
@@ -36,6 +36,7 @@ from django.utils.translation import gettext as _
|
|||||||
|
|
||||||
# In this serializer file
|
# In this serializer file
|
||||||
# define user serializer,
|
# define user serializer,
|
||||||
|
# define password validation
|
||||||
# create guardian serializer,
|
# create guardian serializer,
|
||||||
# task serializer,
|
# task serializer,
|
||||||
# guardian serializer,
|
# guardian serializer,
|
||||||
@@ -47,6 +48,7 @@ from django.utils.translation import gettext as _
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
class PasswordValidator:
|
class PasswordValidator:
|
||||||
|
"""Password validation"""
|
||||||
def __init__(self, min_length=8, max_length=None, require_uppercase=True, require_numbers=True):
|
def __init__(self, min_length=8, max_length=None, require_uppercase=True, require_numbers=True):
|
||||||
self.min_length = min_length
|
self.min_length = min_length
|
||||||
self.max_length = max_length
|
self.max_length = max_length
|
||||||
@@ -57,6 +59,7 @@ class PasswordValidator:
|
|||||||
self.enforce_password_policy(value)
|
self.enforce_password_policy(value)
|
||||||
|
|
||||||
def enforce_password_policy(self, password):
|
def enforce_password_policy(self, password):
|
||||||
|
# add validation for password
|
||||||
special_characters = "!@#$%^&*()_-+=<>?/[]{}|"
|
special_characters = "!@#$%^&*()_-+=<>?/[]{}|"
|
||||||
if len(password) < self.min_length:
|
if len(password) < self.min_length:
|
||||||
raise serializers.ValidationError(
|
raise serializers.ValidationError(
|
||||||
@@ -64,16 +67,20 @@ class PasswordValidator:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if self.max_length is not None and len(password) > self.max_length:
|
if self.max_length is not None and len(password) > self.max_length:
|
||||||
|
# must be 8 character
|
||||||
raise serializers.ValidationError(
|
raise serializers.ValidationError(
|
||||||
_("Password must be at most %(max_length)d characters long.") % {'max_length': self.max_length}
|
_("Password must be at most %(max_length)d characters long.") % {'max_length': self.max_length}
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.require_uppercase and not any(char.isupper() for char in password):
|
if self.require_uppercase and not any(char.isupper() for char in password):
|
||||||
|
# must contain upper case letter
|
||||||
raise serializers.ValidationError(_("Password must contain at least one uppercase letter."))
|
raise serializers.ValidationError(_("Password must contain at least one uppercase letter."))
|
||||||
|
|
||||||
if self.require_numbers and not any(char.isdigit() for char in password):
|
if self.require_numbers and not any(char.isdigit() for char in password):
|
||||||
|
# must contain digit
|
||||||
raise serializers.ValidationError(_("Password must contain at least one digit."))
|
raise serializers.ValidationError(_("Password must contain at least one digit."))
|
||||||
if self.require_numbers and not any(char in special_characters for char in password):
|
if self.require_numbers and not any(char in special_characters for char in password):
|
||||||
|
# must contain special character
|
||||||
raise serializers.ValidationError(_("Password must contain at least one special character."))
|
raise serializers.ValidationError(_("Password must contain at least one special character."))
|
||||||
|
|
||||||
|
|
||||||
@@ -211,7 +218,7 @@ class TaskSerializer(serializers.ModelSerializer):
|
|||||||
class Meta(object):
|
class Meta(object):
|
||||||
"""Meta info"""
|
"""Meta info"""
|
||||||
model = JuniorTask
|
model = JuniorTask
|
||||||
fields = ['id', 'task_name','task_description','points', 'due_date', 'junior', 'default_image']
|
fields = ['id', 'task_name','task_description','points', 'due_date','default_image']
|
||||||
|
|
||||||
def validate_due_date(self, value):
|
def validate_due_date(self, value):
|
||||||
"""validation on due date"""
|
"""validation on due date"""
|
||||||
@@ -222,11 +229,21 @@ class TaskSerializer(serializers.ModelSerializer):
|
|||||||
return value
|
return value
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
"""create default task image data"""
|
"""create default task image data"""
|
||||||
validated_data['guardian'] = Guardian.objects.filter(user=self.context['user']).last()
|
guardian = Guardian.objects.filter(user=self.context['user']).last()
|
||||||
# update image of the task
|
# update image of the task
|
||||||
images = self.context['image']
|
images = self.context['image']
|
||||||
validated_data['default_image'] = images
|
junior_ids = self.context['junior_data']
|
||||||
instance = JuniorTask.objects.create(**validated_data)
|
junior_data = junior_ids[0].split(',')
|
||||||
|
tasks_created = []
|
||||||
|
|
||||||
|
for junior_id in junior_data:
|
||||||
|
# create task
|
||||||
|
task_data = validated_data.copy()
|
||||||
|
task_data['guardian'] = guardian
|
||||||
|
task_data['default_image'] = images
|
||||||
|
task_data['junior'] = Junior.objects.filter(id=junior_id).last()
|
||||||
|
instance = JuniorTask.objects.create(**task_data)
|
||||||
|
tasks_created.append(instance)
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
class GuardianDetailSerializer(serializers.ModelSerializer):
|
class GuardianDetailSerializer(serializers.ModelSerializer):
|
||||||
@@ -316,10 +333,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 +347,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"""
|
||||||
@@ -390,9 +412,9 @@ class ApproveJuniorSerializer(serializers.ModelSerializer):
|
|||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
"""update guardian code"""
|
"""update guardian code"""
|
||||||
instance = self.context['junior']
|
instance = self.context['junior']
|
||||||
instance.guardian_code = [self.context['guardian_code']]
|
guardian_code = self.context['guardian_code']
|
||||||
instance.guardian_code_approved = True
|
index = instance.guardian_code.index(guardian_code)
|
||||||
instance.guardian_code_status = str(NUMBER['two'])
|
instance.guardian_code_status[index] = str(NUMBER['two'])
|
||||||
instance.save()
|
instance.save()
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
@@ -500,4 +522,7 @@ class GuardianDetailListSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
def get_guardian_code_status(self,obj):
|
def get_guardian_code_status(self,obj):
|
||||||
"""guardian code status"""
|
"""guardian code status"""
|
||||||
return obj.junior.guardian_code_status
|
if obj.guardian.guardian_code in obj.junior.guardian_code:
|
||||||
|
index = obj.junior.guardian_code.index(obj.guardian.guardian_code)
|
||||||
|
data = obj.junior.guardian_code_status[index]
|
||||||
|
return data
|
||||||
|
|||||||
+1
-1
@@ -127,7 +127,7 @@ def update_expired_task_status(data=None):
|
|||||||
Update task of the status if due date is in past
|
Update task of the status if due date is in past
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
task_status = [str(NUMBER['one']), str(NUMBER['two']), str(NUMBER['four'])]
|
task_status = [str(NUMBER['one']), str(NUMBER['two'])]
|
||||||
JuniorTask.objects.filter(due_date__lt=datetime.today().date(),
|
JuniorTask.objects.filter(due_date__lt=datetime.today().date(),
|
||||||
task_status__in=task_status).update(task_status=str(NUMBER['six']))
|
task_status__in=task_status).update(task_status=str(NUMBER['six']))
|
||||||
except ObjectDoesNotExist as e:
|
except ObjectDoesNotExist as e:
|
||||||
|
|||||||
+84
-49
@@ -1,4 +1,5 @@
|
|||||||
"""Views of Guardian"""
|
"""Views of Guardian"""
|
||||||
|
import math
|
||||||
|
|
||||||
# django imports
|
# django imports
|
||||||
# Import IsAuthenticated
|
# Import IsAuthenticated
|
||||||
@@ -6,11 +7,13 @@
|
|||||||
# 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
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from base.constants import guardian_code_tuple
|
||||||
from rest_framework.filters import SearchFilter
|
from rest_framework.filters import SearchFilter
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
@@ -34,7 +37,7 @@ from .models import Guardian, JuniorTask
|
|||||||
from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship
|
from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship
|
||||||
from account.models import UserEmailOtp, UserNotification, UserDeviceDetails
|
from account.models import UserEmailOtp, UserNotification, UserDeviceDetails
|
||||||
from .tasks import generate_otp
|
from .tasks import generate_otp
|
||||||
from account.utils import custom_response, custom_error_response, OTP_EXPIRY, send_otp_email
|
from account.utils import custom_response, custom_error_response, send_otp_email, task_status_fun
|
||||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||||
from base.constants import NUMBER, GUARDIAN_CODE_STATUS, GUARDIAN
|
from base.constants import NUMBER, GUARDIAN_CODE_STATUS, GUARDIAN
|
||||||
from .utils import upload_image_to_alibaba
|
from .utils import upload_image_to_alibaba
|
||||||
@@ -133,7 +136,8 @@ class TaskListAPIView(viewsets.ModelViewSet):
|
|||||||
Params
|
Params
|
||||||
status
|
status
|
||||||
search
|
search
|
||||||
page"""
|
page
|
||||||
|
junior"""
|
||||||
serializer_class = TaskDetailsSerializer
|
serializer_class = TaskDetailsSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
filter_backends = (SearchFilter,)
|
filter_backends = (SearchFilter,)
|
||||||
@@ -152,15 +156,23 @@ class TaskListAPIView(viewsets.ModelViewSet):
|
|||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
"""Create guardian profile"""
|
"""Create guardian profile"""
|
||||||
status_value = self.request.GET.get('status')
|
status_value = self.request.GET.get('status')
|
||||||
|
current_page = self.request.GET.get('page')
|
||||||
|
junior = self.request.GET.get('junior')
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_queryset()
|
||||||
if status_value and status_value != '0':
|
task_status = task_status_fun(status_value)
|
||||||
queryset = queryset.filter(task_status=status_value)
|
if status_value and not junior:
|
||||||
|
queryset = queryset.filter(task_status__in=task_status)
|
||||||
|
elif status_value and junior:
|
||||||
|
queryset = queryset.filter(task_status__in=task_status,junior=int(junior))
|
||||||
paginator = self.pagination_class()
|
paginator = self.pagination_class()
|
||||||
|
total_count = len(queryset)
|
||||||
|
total_pages = math.ceil(total_count/10)
|
||||||
# use Pagination
|
# use Pagination
|
||||||
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
||||||
# use TaskDetailsSerializer serializer
|
# use TaskDetailsSerializer serializer
|
||||||
serializer = self.serializer_class(paginated_queryset, many=True)
|
serializer = self.serializer_class(paginated_queryset, many=True)
|
||||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
return custom_response(None, serializer.data, total_pages=total_pages, current_page=current_page,
|
||||||
|
response_status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
class CreateTaskAPIView(viewsets.ModelViewSet):
|
class CreateTaskAPIView(viewsets.ModelViewSet):
|
||||||
@@ -175,37 +187,46 @@ class CreateTaskAPIView(viewsets.ModelViewSet):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
image = request.data['default_image']
|
image = request.data['default_image']
|
||||||
junior = request.data['junior']
|
juniors = request.data['junior'].split(',')
|
||||||
junior_id = Junior.objects.filter(id=junior).last()
|
for junior in juniors:
|
||||||
guardian_data = Guardian.objects.filter(user=request.user).last()
|
junior_id = Junior.objects.filter(id=junior).last()
|
||||||
if guardian_data.guardian_code not in junior_id.guardian_code:
|
if junior_id:
|
||||||
return custom_error_response(ERROR_CODE['2078'], response_status=status.HTTP_400_BAD_REQUEST)
|
guardian_data = Guardian.objects.filter(user=request.user).last()
|
||||||
allowed_extensions = ['.jpg', '.jpeg', '.png']
|
index = junior_id.guardian_code.index(guardian_data.guardian_code)
|
||||||
if not any(extension in str(image) for extension in allowed_extensions):
|
status_index = junior_id.guardian_code_status[index]
|
||||||
return custom_error_response(ERROR_CODE['2048'], response_status=status.HTTP_400_BAD_REQUEST)
|
if status_index == str(NUMBER['three']):
|
||||||
if not junior.isnumeric():
|
return custom_error_response(ERROR_CODE['2078'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
"""junior value must be integer"""
|
allowed_extensions = ['.jpg', '.jpeg', '.png']
|
||||||
return custom_error_response(ERROR_CODE['2047'], response_status=status.HTTP_400_BAD_REQUEST)
|
if not any(extension in str(image) for extension in allowed_extensions):
|
||||||
data = request.data
|
return custom_error_response(ERROR_CODE['2048'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
if 'https' in str(image):
|
if not junior.isnumeric():
|
||||||
image_data = image
|
"""junior value must be integer"""
|
||||||
else:
|
return custom_error_response(ERROR_CODE['2047'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
filename = f"images/{image}"
|
data = request.data
|
||||||
if image and image.size == NUMBER['zero']:
|
if 'https' in str(image):
|
||||||
return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST)
|
image_data = image
|
||||||
image_url = upload_image_to_alibaba(image, filename)
|
else:
|
||||||
image_data = image_url
|
filename = f"images/{image}"
|
||||||
data.pop('default_image')
|
if image and image.size == NUMBER['zero']:
|
||||||
# use TaskSerializer serializer
|
return custom_error_response(ERROR_CODE['2035'],
|
||||||
serializer = TaskSerializer(context={"user":request.user, "image":image_data}, data=data)
|
response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
if serializer.is_valid():
|
image_url = upload_image_to_alibaba(image, filename)
|
||||||
# save serializer
|
image_data = image_url
|
||||||
task = serializer.save()
|
data.pop('default_image')
|
||||||
|
junior_data = data.pop('junior')
|
||||||
|
# use TaskSerializer serializer
|
||||||
|
serializer = TaskSerializer(context={"user":request.user, "image":image_data,
|
||||||
|
"junior_data":junior_data}, data=data)
|
||||||
|
if serializer.is_valid():
|
||||||
|
# save serializer
|
||||||
|
task = serializer.save()
|
||||||
|
|
||||||
send_notification.delay(TASK_ASSIGNED, request.auth.payload['user_id'], GUARDIAN,
|
send_notification.delay(TASK_ASSIGNED, request.auth.payload['user_id'], GUARDIAN,
|
||||||
junior_id.auth.id, {'task_id': task.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'], 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:
|
||||||
|
return custom_error_response(ERROR_CODE['2047'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
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)
|
||||||
|
|
||||||
@@ -241,7 +262,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',)
|
||||||
@@ -252,15 +272,22 @@ class TopJuniorListAPIView(viewsets.ModelViewSet):
|
|||||||
context.update({'view': self})
|
context.update({'view': self})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = JuniorPoints.objects.filter(
|
||||||
|
junior__is_verified=True
|
||||||
|
).select_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)
|
||||||
@@ -287,19 +314,25 @@ class ApproveJuniorAPIView(viewsets.ModelViewSet):
|
|||||||
if request.data['action'] == '1':
|
if request.data['action'] == '1':
|
||||||
# use ApproveJuniorSerializer serializer
|
# use ApproveJuniorSerializer serializer
|
||||||
serializer = ApproveJuniorSerializer(context={"guardian_code": guardian.guardian_code,
|
serializer = ApproveJuniorSerializer(context={"guardian_code": guardian.guardian_code,
|
||||||
"junior": junior_queryset, "action": request.data['action']},
|
"junior": junior_queryset,
|
||||||
|
"action": request.data['action']},
|
||||||
data=request.data)
|
data=request.data)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
# save serializer
|
# save serializer
|
||||||
serializer.save()
|
serializer.save()
|
||||||
send_notification.delay(ASSOCIATE_APPROVED, guardian.user.id, GUARDIAN,
|
send_notification.delay(ASSOCIATE_APPROVED, guardian.user.id, GUARDIAN,
|
||||||
junior_queryset.auth.id)
|
junior_queryset.auth.id, {})
|
||||||
return custom_response(SUCCESS_CODE['3023'], serializer.data, response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3023'], serializer.data, response_status=status.HTTP_200_OK)
|
||||||
else:
|
else:
|
||||||
junior_queryset.guardian_code = None
|
if junior_queryset.guardian_code and ('-' in junior_queryset.guardian_code):
|
||||||
junior_queryset.guardian_code_status = str(NUMBER['one'])
|
junior_queryset.guardian_code.remove('-')
|
||||||
|
if junior_queryset.guardian_code_status and ('-' in junior_queryset.guardian_code_status):
|
||||||
|
junior_queryset.guardian_code_status.remove('-')
|
||||||
|
index = junior_queryset.guardian_code.index(guardian.guardian_code)
|
||||||
|
junior_queryset.guardian_code.remove(guardian.guardian_code)
|
||||||
|
junior_queryset.guardian_code_status.pop(index)
|
||||||
junior_queryset.save()
|
junior_queryset.save()
|
||||||
send_notification.delay(ASSOCIATE_REJECTED, guardian.user.id, GUARDIAN, junior_queryset.auth.id)
|
send_notification.delay(ASSOCIATE_REJECTED, guardian.user.id, GUARDIAN, junior_queryset.auth.id, {})
|
||||||
return custom_response(SUCCESS_CODE['3024'], response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3024'], 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)
|
||||||
@@ -325,6 +358,8 @@ class ApproveTaskAPIView(viewsets.ModelViewSet):
|
|||||||
task_queryset = JuniorTask.objects.filter(id=self.request.data.get('task_id'),
|
task_queryset = JuniorTask.objects.filter(id=self.request.data.get('task_id'),
|
||||||
guardian=guardian,
|
guardian=guardian,
|
||||||
junior=self.request.data.get('junior_id')).last()
|
junior=self.request.data.get('junior_id')).last()
|
||||||
|
if task_queryset and guardian.guardian_code not in task_queryset.junior.guardian_code:
|
||||||
|
return custom_error_response(ERROR_CODE['2084'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
if task_queryset and (task_queryset.junior.is_deleted or not task_queryset.junior.is_active):
|
if task_queryset and (task_queryset.junior.is_deleted or not task_queryset.junior.is_active):
|
||||||
return custom_error_response(ERROR_CODE['2072'], response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE['2072'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
# use ApproveJuniorSerializer serializer
|
# use ApproveJuniorSerializer serializer
|
||||||
@@ -348,7 +383,7 @@ class ApproveTaskAPIView(viewsets.ModelViewSet):
|
|||||||
return custom_error_response(ERROR_CODE['2038'], response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE['2038'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
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)
|
||||||
|
#
|
||||||
class GuardianListAPIView(viewsets.ModelViewSet):
|
class GuardianListAPIView(viewsets.ModelViewSet):
|
||||||
"""Guardian list of assosicated junior"""
|
"""Guardian list of assosicated junior"""
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 4.2.2 on 2023-08-26 08:59
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('junior', '0029_junior_is_deleted'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='junior',
|
||||||
|
name='guardian_code_status',
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 4.2.2 on 2023-08-26 08:59
|
||||||
|
|
||||||
|
import django.contrib.postgres.fields
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('junior', '0030_remove_junior_guardian_code_status'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='junior',
|
||||||
|
name='guardian_code_status',
|
||||||
|
field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, default=None, max_length=10, null=True), null=True, size=None),
|
||||||
|
),
|
||||||
|
]
|
||||||
+3
-3
@@ -76,9 +76,9 @@ class Junior(models.Model):
|
|||||||
is_verified = models.BooleanField(default=False)
|
is_verified = models.BooleanField(default=False)
|
||||||
"""guardian code is approved or not"""
|
"""guardian code is approved or not"""
|
||||||
guardian_code_approved = models.BooleanField(default=False)
|
guardian_code_approved = models.BooleanField(default=False)
|
||||||
# guardian code status"""
|
# # guardian code status"""
|
||||||
guardian_code_status = models.CharField(max_length=31, choices=GUARDIAN_CODE_STATUS, default='1',
|
guardian_code_status = ArrayField(models.CharField(max_length=10, null=True, blank=True, default=None), null=True,
|
||||||
null=True, blank=True)
|
)
|
||||||
# Profile created and updated time"""
|
# Profile created and updated time"""
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
|||||||
+58
-34
@@ -11,7 +11,7 @@ from django.utils import timezone
|
|||||||
from rest_framework_simplejwt.tokens import RefreshToken
|
from rest_framework_simplejwt.tokens import RefreshToken
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from account.utils import send_otp_email, generate_code
|
from account.utils import send_otp_email, generate_code, make_special_password
|
||||||
from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints, FAQ
|
from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints, FAQ
|
||||||
from guardian.tasks import generate_otp
|
from guardian.tasks import generate_otp
|
||||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||||
@@ -19,10 +19,10 @@ 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, ASSOCIATE_JUNIOR, TASK_ACTION,
|
||||||
)
|
)
|
||||||
from web_admin.models import ArticleCard
|
from web_admin.models import ArticleCard
|
||||||
|
|
||||||
@@ -88,18 +88,27 @@ class CreateJuniorSerializer(serializers.ModelSerializer):
|
|||||||
if junior:
|
if junior:
|
||||||
"""update details according to the data get from request"""
|
"""update details according to the data get from request"""
|
||||||
junior.gender = validated_data.get('gender',junior.gender)
|
junior.gender = validated_data.get('gender',junior.gender)
|
||||||
"""Update guardian code"""
|
# Update guardian code"""
|
||||||
junior.guardian_code = validated_data.get('guardian_code', junior.guardian_code)
|
# condition for guardian code
|
||||||
"""condition for guardian code"""
|
|
||||||
if guardian_code:
|
if guardian_code:
|
||||||
junior.guardian_code = guardian_code
|
if junior.guardian_code and guardian_code:
|
||||||
|
if guardian_code[0] in junior.guardian_code:
|
||||||
|
raise serializers.ValidationError({"error":ERROR_CODE['2076'],"code":"400", "status":"failed"})
|
||||||
|
if not junior.guardian_code:
|
||||||
|
junior.guardian_code = []
|
||||||
|
junior.guardian_code_status = []
|
||||||
|
junior.guardian_code.extend(guardian_code)
|
||||||
|
junior.guardian_code_status.extend(str(NUMBER['three']))
|
||||||
|
elif len(junior.guardian_code) < 3 and len(guardian_code) < 3:
|
||||||
|
junior.guardian_code.extend(guardian_code)
|
||||||
|
junior.guardian_code_status.extend(str(NUMBER['three']))
|
||||||
|
else:
|
||||||
|
raise serializers.ValidationError({"error":ERROR_CODE['2081'],"code":"400", "status":"failed"})
|
||||||
guardian_data = Guardian.objects.filter(guardian_code=guardian_code[0]).last()
|
guardian_data = Guardian.objects.filter(guardian_code=guardian_code[0]).last()
|
||||||
if guardian_data:
|
if guardian_data:
|
||||||
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'])
|
send_notification.delay(ASSOCIATE_REQUEST, junior.auth.id, JUNIOR, guardian_data.user.id, {})
|
||||||
junior_approval_mail.delay(user.email, user.first_name)
|
junior_approval_mail.delay(user.email, user.first_name)
|
||||||
send_notification.delay(ASSOCIATE_REQUEST, junior.auth.id, JUNIOR, 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)
|
||||||
@@ -164,6 +173,7 @@ class JuniorDetailListSerializer(serializers.ModelSerializer):
|
|||||||
rejected_task = serializers.SerializerMethodField('get_rejected_task')
|
rejected_task = serializers.SerializerMethodField('get_rejected_task')
|
||||||
pending_task = serializers.SerializerMethodField('get_pending_task')
|
pending_task = serializers.SerializerMethodField('get_pending_task')
|
||||||
position = serializers.SerializerMethodField('get_position')
|
position = serializers.SerializerMethodField('get_position')
|
||||||
|
guardian_code_status = serializers.SerializerMethodField('get_guardian_code_status')
|
||||||
|
|
||||||
|
|
||||||
def get_auth(self, obj):
|
def get_auth(self, obj):
|
||||||
@@ -180,9 +190,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:
|
||||||
@@ -209,6 +218,13 @@ class JuniorDetailListSerializer(serializers.ModelSerializer):
|
|||||||
def get_pending_task(self, obj):
|
def get_pending_task(self, obj):
|
||||||
data = JuniorTask.objects.filter(junior=obj, task_status=PENDING).count()
|
data = JuniorTask.objects.filter(junior=obj, task_status=PENDING).count()
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def get_guardian_code_status(self, obj):
|
||||||
|
if self.context['guardian_code'] in obj.guardian_code:
|
||||||
|
index = obj.guardian_code.index(self.context['guardian_code'])
|
||||||
|
if obj.guardian_code_status:
|
||||||
|
data = obj.guardian_code_status[index]
|
||||||
|
return data
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
"""Meta info"""
|
"""Meta info"""
|
||||||
model = Junior
|
model = Junior
|
||||||
@@ -281,8 +297,8 @@ class AddJuniorSerializer(serializers.ModelSerializer):
|
|||||||
user_data = User.objects.create(username=email, email=email,
|
user_data = User.objects.create(username=email, email=email,
|
||||||
first_name=self.context['first_name'],
|
first_name=self.context['first_name'],
|
||||||
last_name=self.context['last_name'])
|
last_name=self.context['last_name'])
|
||||||
password = User.objects.make_random_password()
|
special_password = make_special_password()
|
||||||
user_data.set_password(password)
|
user_data.set_password(special_password)
|
||||||
user_data.save()
|
user_data.save()
|
||||||
junior_data = Junior.objects.create(auth=user_data, gender=validated_data.get('gender'),
|
junior_data = Junior.objects.create(auth=user_data, gender=validated_data.get('gender'),
|
||||||
image=profile_image,
|
image=profile_image,
|
||||||
@@ -292,8 +308,8 @@ class AddJuniorSerializer(serializers.ModelSerializer):
|
|||||||
referral_code=generate_code(ZOD, user_data.id),
|
referral_code=generate_code(ZOD, user_data.id),
|
||||||
referral_code_used=guardian_data.referral_code,
|
referral_code_used=guardian_data.referral_code,
|
||||||
is_password_set=False, is_verified=True,
|
is_password_set=False, is_verified=True,
|
||||||
guardian_code_status=GUARDIAN_CODE_STATUS[1][0])
|
guardian_code_status=[str(NUMBER['two'])])
|
||||||
JuniorGuardianRelationship.objects.get_or_create(guardian=guardian_data, junior=junior_data,
|
JuniorGuardianRelationship.objects.create(guardian=guardian_data, junior=junior_data,
|
||||||
relationship=relationship)
|
relationship=relationship)
|
||||||
total_junior = Junior.objects.all().count()
|
total_junior = Junior.objects.all().count()
|
||||||
JuniorPoints.objects.create(junior=junior_data, position=total_junior)
|
JuniorPoints.objects.create(junior=junior_data, position=total_junior)
|
||||||
@@ -305,9 +321,9 @@ class AddJuniorSerializer(serializers.ModelSerializer):
|
|||||||
# add push notification
|
# add push notification
|
||||||
UserNotification.objects.get_or_create(user=user_data)
|
UserNotification.objects.get_or_create(user=user_data)
|
||||||
"""Notification email"""
|
"""Notification email"""
|
||||||
junior_notification_email.delay(email, full_name, email, password)
|
junior_notification_email.delay(email, full_name, email, special_password)
|
||||||
# push notification
|
# push notification
|
||||||
send_notification.delay(JUNIOR_ADDED, None, None, junior_data.auth.id, {})
|
send_notification.delay(ASSOCIATE_JUNIOR, None, None, junior_data.auth.id, {})
|
||||||
return junior_data
|
return junior_data
|
||||||
|
|
||||||
|
|
||||||
@@ -320,9 +336,13 @@ class RemoveJuniorSerializer(serializers.ModelSerializer):
|
|||||||
fields = ('id', 'is_invited')
|
fields = ('id', 'is_invited')
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
if instance:
|
if instance:
|
||||||
|
guardian_code = self.context['guardian_code']
|
||||||
instance.is_invited = False
|
instance.is_invited = False
|
||||||
instance.guardian_code = '{}'
|
if instance.guardian_code and ('-' in instance.guardian_code):
|
||||||
instance.guardian_code_status = str(NUMBER['one'])
|
instance.guardian_code.remove('-')
|
||||||
|
index = instance.guardian_code.index(guardian_code)
|
||||||
|
instance.guardian_code.remove(guardian_code)
|
||||||
|
instance.guardian_code_status.pop(index)
|
||||||
instance.save()
|
instance.save()
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
@@ -360,10 +380,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()
|
||||||
@@ -444,7 +461,7 @@ class AddGuardianSerializer(serializers.ModelSerializer):
|
|||||||
user_type=str(NUMBER['two']), expired_at=expiry_time,
|
user_type=str(NUMBER['two']), expired_at=expiry_time,
|
||||||
is_verified=True)
|
is_verified=True)
|
||||||
UserNotification.objects.get_or_create(user=user)
|
UserNotification.objects.get_or_create(user=user)
|
||||||
JuniorGuardianRelationship.objects.get_or_create(guardian=guardian_data, junior=junior_data,
|
JuniorGuardianRelationship.objects.create(guardian=guardian_data, junior=junior_data,
|
||||||
relationship=relationship)
|
relationship=relationship)
|
||||||
|
|
||||||
"""Notification email"""
|
"""Notification email"""
|
||||||
@@ -494,8 +511,6 @@ class ReAssignTaskSerializer(serializers.ModelSerializer):
|
|||||||
instance.save()
|
instance.save()
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RemoveGuardianCodeSerializer(serializers.ModelSerializer):
|
class RemoveGuardianCodeSerializer(serializers.ModelSerializer):
|
||||||
"""User task Serializer"""
|
"""User task Serializer"""
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
@@ -503,24 +518,33 @@ 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
|
guardian_code = self.context['guardian_code']
|
||||||
instance.guardian_code_status = str(NUMBER['one'])
|
if guardian_code in instance.guardian_code:
|
||||||
|
if instance.guardian_code and ('-' in instance.guardian_code):
|
||||||
|
instance.guardian_code.remove('-')
|
||||||
|
if instance.guardian_code_status and ('-' in instance.guardian_code_status):
|
||||||
|
instance.guardian_code_status.remove('-')
|
||||||
|
index = instance.guardian_code.index(guardian_code)
|
||||||
|
instance.guardian_code.remove(guardian_code)
|
||||||
|
instance.guardian_code_status.pop(index)
|
||||||
|
else:
|
||||||
|
raise serializers.ValidationError({"error":ERROR_CODE['2082'],"code":"400", "status":"failed"})
|
||||||
instance.save()
|
instance.save()
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
class FAQSerializer(serializers.ModelSerializer):
|
class FAQSerializer(serializers.ModelSerializer):
|
||||||
# FAQ Serializer
|
"""FAQ Serializer"""
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
# meta info
|
"""meta info"""
|
||||||
model = FAQ
|
model = FAQ
|
||||||
fields = ('id', 'question', 'description')
|
fields = ('id', 'question', 'description')
|
||||||
|
|
||||||
class CreateArticleCardSerializer(serializers.ModelSerializer):
|
class CreateArticleCardSerializer(serializers.ModelSerializer):
|
||||||
# Article card Serializer
|
"""Article card Serializer"""
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
# meta info
|
"""meta info"""
|
||||||
model = ArticleCard
|
model = ArticleCard
|
||||||
fields = ('id', 'article')
|
fields = ('id', 'article')
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -62,5 +62,5 @@ urlpatterns = [
|
|||||||
path('api/v1/reassign-task/', ReAssignJuniorTaskAPIView.as_view()),
|
path('api/v1/reassign-task/', ReAssignJuniorTaskAPIView.as_view()),
|
||||||
path('api/v1/complete-article/', CompleteArticleAPIView.as_view()),
|
path('api/v1/complete-article/', CompleteArticleAPIView.as_view()),
|
||||||
path('api/v1/read-article-card/', ReadArticleCardAPIView.as_view()),
|
path('api/v1/read-article-card/', ReadArticleCardAPIView.as_view()),
|
||||||
path('api/v1/remove-guardian-code-request/', RemoveGuardianCodeAPIView.as_view()),
|
path('api/v1/remove-guardian-code-request/', RemoveGuardianCodeAPIView.as_view())
|
||||||
]
|
]
|
||||||
|
|||||||
+20
-1
@@ -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,21 @@ 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.filter(
|
||||||
|
junior__is_verified=True
|
||||||
|
).select_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
|
||||||
|
|||||||
+83
-44
@@ -12,6 +12,7 @@ import datetime
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from rest_framework.viewsets import GenericViewSet, mixins
|
from rest_framework.viewsets import GenericViewSet, mixins
|
||||||
|
import math
|
||||||
"""Django app import"""
|
"""Django app import"""
|
||||||
from drf_yasg.utils import swagger_auto_schema
|
from drf_yasg.utils import swagger_auto_schema
|
||||||
from drf_yasg import openapi
|
from drf_yasg import openapi
|
||||||
@@ -42,12 +43,12 @@ from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, Ad
|
|||||||
from guardian.models import Guardian, JuniorTask
|
from guardian.models import Guardian, JuniorTask
|
||||||
from guardian.serializers import TaskDetailsSerializer, TaskDetailsjuniorSerializer
|
from guardian.serializers import TaskDetailsSerializer, TaskDetailsjuniorSerializer
|
||||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||||
from base.constants import NUMBER, ARTICLE_STATUS, none
|
from base.constants import NUMBER, ARTICLE_STATUS, none, GUARDIAN
|
||||||
from account.utils import custom_response, custom_error_response
|
from account.utils import custom_response, custom_error_response, task_status_fun
|
||||||
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
|
from notifications.utils import send_notification
|
||||||
from notifications.constants import REMOVE_JUNIOR
|
from notifications.constants import REMOVE_JUNIOR, ARTICLE_REWARD_POINTS, ASSOCIATE_EXISTING_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,
|
||||||
StartAssessmentSerializer)
|
StartAssessmentSerializer)
|
||||||
@@ -99,7 +100,11 @@ class UpdateJuniorProfile(viewsets.ModelViewSet):
|
|||||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
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)
|
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
if e.detail:
|
||||||
|
error_detail = e.detail.get('error', None)
|
||||||
|
else:
|
||||||
|
error_detail = str(e)
|
||||||
|
return custom_error_response(error_detail, response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
class ValidateGuardianCode(viewsets.ModelViewSet):
|
class ValidateGuardianCode(viewsets.ModelViewSet):
|
||||||
"""Check guardian code exist or not"""
|
"""Check guardian code exist or not"""
|
||||||
@@ -141,14 +146,15 @@ 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:
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_queryset()
|
||||||
queryset = queryset.filter(guardian_code__icontains=str(guardian_data.guardian_code))
|
queryset = queryset.filter(guardian_code__icontains=str(guardian_data.guardian_code))
|
||||||
# use JuniorDetailListSerializer serializer
|
# use JuniorDetailListSerializer serializer
|
||||||
serializer = JuniorDetailListSerializer(queryset, many=True)
|
serializer = JuniorDetailListSerializer(queryset, context={"guardian_code":
|
||||||
|
guardian_data.guardian_code}, 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)
|
||||||
return custom_error_response(ERROR_CODE['2045'], response_status=status.HTTP_200_OK)
|
return custom_error_response(ERROR_CODE['2045'], response_status=status.HTTP_200_OK)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -190,6 +196,8 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
|
|||||||
return custom_error_response(ERROR_CODE['2077'], response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE['2077'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
elif not data:
|
elif not data:
|
||||||
return custom_error_response(ERROR_CODE['2076'], response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE['2076'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
elif data == "Max":
|
||||||
|
return custom_error_response(ERROR_CODE['2081'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
return custom_response(SUCCESS_CODE['3021'], response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3021'], response_status=status.HTTP_200_OK)
|
||||||
# use AddJuniorSerializer serializer
|
# use AddJuniorSerializer serializer
|
||||||
serializer = AddJuniorSerializer(data=request.data, context=info_data)
|
serializer = AddJuniorSerializer(data=request.data, context=info_data)
|
||||||
@@ -204,18 +212,30 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
|
|||||||
def associate_guardian(self, user):
|
def associate_guardian(self, user):
|
||||||
junior = Junior.objects.filter(auth__email=self.request.data['email']).first()
|
junior = Junior.objects.filter(auth__email=self.request.data['email']).first()
|
||||||
guardian = Guardian.objects.filter(user=self.request.user).first()
|
guardian = Guardian.objects.filter(user=self.request.user).first()
|
||||||
if not junior:
|
if junior is None:
|
||||||
return none
|
return none
|
||||||
if junior.guardian_code and (guardian.guardian_code in junior.guardian_code):
|
if junior.guardian_code and (guardian.guardian_code in junior.guardian_code):
|
||||||
return False
|
return False
|
||||||
if type(junior.guardian_code) is list:
|
if junior.guardian_code and ('-' in junior.guardian_code):
|
||||||
|
junior.guardian_code.remove('-')
|
||||||
|
if not junior.guardian_code:
|
||||||
|
junior.guardian_code = [guardian.guardian_code]
|
||||||
|
elif type(junior.guardian_code) is list and len(junior.guardian_code) < 3:
|
||||||
junior.guardian_code.append(guardian.guardian_code)
|
junior.guardian_code.append(guardian.guardian_code)
|
||||||
else:
|
else:
|
||||||
junior.guardian_code = [guardian.guardian_code]
|
return "Max"
|
||||||
junior.guardian_code_status = str(NUMBER['two'])
|
if junior.guardian_code_status and ('-' in junior.guardian_code_status):
|
||||||
|
junior.guardian_code_status.remove('-')
|
||||||
|
if not junior.guardian_code_status:
|
||||||
|
junior.guardian_code_status = [str(NUMBER['two'])]
|
||||||
|
else:
|
||||||
|
junior.guardian_code_status.append(str(NUMBER['two']))
|
||||||
junior.save()
|
junior.save()
|
||||||
JuniorGuardianRelationship.objects.get_or_create(guardian=guardian, junior=junior,
|
jun_data, created = JuniorGuardianRelationship.objects.get_or_create(guardian=guardian, junior=junior)
|
||||||
relationship=str(self.request.data['relationship']))
|
if jun_data:
|
||||||
|
jun_data.relationship = str(self.request.data['relationship'])
|
||||||
|
jun_data.save()
|
||||||
|
send_notification.delay(ASSOCIATE_EXISTING_JUNIOR, self.request.user.id, GUARDIAN, junior.auth.id, {})
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@@ -259,10 +279,10 @@ class FilterJuniorAPIView(viewsets.ModelViewSet):
|
|||||||
manual_parameters=[
|
manual_parameters=[
|
||||||
# Example of a query parameter
|
# Example of a query parameter
|
||||||
openapi.Parameter(
|
openapi.Parameter(
|
||||||
'title', # Query parameter name
|
'title',
|
||||||
openapi.IN_QUERY, # Parameter location
|
openapi.IN_QUERY,
|
||||||
description='title of the name',
|
description='title of the name',
|
||||||
type=openapi.TYPE_STRING, # Parameter type
|
type=openapi.TYPE_STRING,
|
||||||
),
|
),
|
||||||
# Add more parameters as needed
|
# Add more parameters as needed
|
||||||
]
|
]
|
||||||
@@ -308,10 +328,12 @@ class RemoveJuniorAPIView(views.APIView):
|
|||||||
guardian_code__icontains=str(guardian.guardian_code)).last()
|
guardian_code__icontains=str(guardian.guardian_code)).last()
|
||||||
if junior_queryset:
|
if junior_queryset:
|
||||||
# use RemoveJuniorSerializer serializer
|
# use RemoveJuniorSerializer serializer
|
||||||
serializer = RemoveJuniorSerializer(junior_queryset, data=request.data, partial=True)
|
serializer = RemoveJuniorSerializer(junior_queryset, context={"guardian_code":guardian.guardian_code},
|
||||||
|
data=request.data, partial=True)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
# save serializer
|
# save serializer
|
||||||
serializer.save()
|
serializer.save()
|
||||||
|
JuniorGuardianRelationship.objects.filter(guardian=guardian, junior=junior_queryset).delete()
|
||||||
send_notification.delay(REMOVE_JUNIOR, None, None, junior_queryset.auth.id, {})
|
send_notification.delay(REMOVE_JUNIOR, None, 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)
|
||||||
@@ -325,9 +347,19 @@ class JuniorTaskListAPIView(viewsets.ModelViewSet):
|
|||||||
"""Junior task list"""
|
"""Junior task list"""
|
||||||
serializer_class = TaskDetailsjuniorSerializer
|
serializer_class = TaskDetailsjuniorSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
filter_backends = (SearchFilter,)
|
||||||
|
search_fields = ['task_name', ]
|
||||||
pagination_class = PageNumberPagination
|
pagination_class = PageNumberPagination
|
||||||
http_method_names = ('get',)
|
http_method_names = ('get',)
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = JuniorTask.objects.filter(junior__auth=self.request.user
|
||||||
|
).prefetch_related('junior', 'junior__auth'
|
||||||
|
).order_by('due_date', 'created_at')
|
||||||
|
|
||||||
|
queryset = self.filter_queryset(queryset)
|
||||||
|
return queryset
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
"""Junior task list
|
"""Junior task list
|
||||||
status=0
|
status=0
|
||||||
@@ -335,28 +367,20 @@ class JuniorTaskListAPIView(viewsets.ModelViewSet):
|
|||||||
page=1"""
|
page=1"""
|
||||||
try:
|
try:
|
||||||
status_value = self.request.GET.get('status')
|
status_value = self.request.GET.get('status')
|
||||||
search = self.request.GET.get('search')
|
current_page = self.request.GET.get('page')
|
||||||
if search and str(status_value) == '0':
|
queryset = self.get_queryset()
|
||||||
# search with title and for all task list
|
task_status = task_status_fun(status_value)
|
||||||
queryset = JuniorTask.objects.filter(junior__auth=request.user,
|
if status_value:
|
||||||
task_name__icontains=search).order_by('due_date', 'created_at')
|
queryset = queryset.filter(task_status__in=task_status)
|
||||||
elif search and str(status_value) != '0':
|
|
||||||
# search with title and fetch task list with status wise
|
|
||||||
queryset = JuniorTask.objects.filter(junior__auth=request.user, task_name__icontains=search,
|
|
||||||
task_status=status_value).order_by('due_date', 'created_at')
|
|
||||||
if search is None and str(status_value) == '0':
|
|
||||||
# fetch all task list
|
|
||||||
queryset = JuniorTask.objects.filter(junior__auth=request.user).order_by('due_date', 'created_at')
|
|
||||||
elif search is None and str(status_value) != '0':
|
|
||||||
# fetch task list with status wise
|
|
||||||
queryset = JuniorTask.objects.filter(junior__auth=request.user,
|
|
||||||
task_status=status_value).order_by('due_date','created_at')
|
|
||||||
paginator = self.pagination_class()
|
paginator = self.pagination_class()
|
||||||
|
total_count = len(queryset)
|
||||||
|
total_pages = math.ceil(total_count / 10)
|
||||||
# use Pagination
|
# use Pagination
|
||||||
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
||||||
# use TaskDetailsSerializer serializer
|
# use TaskDetails juniorSerializer serializer
|
||||||
serializer = TaskDetailsjuniorSerializer(paginated_queryset, many=True)
|
serializer = self.serializer_class(paginated_queryset, many=True)
|
||||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
return custom_response(None, serializer.data, total_pages=total_pages, current_page=current_page,
|
||||||
|
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)
|
||||||
|
|
||||||
@@ -385,10 +409,12 @@ class CompleteJuniorTaskAPIView(views.APIView):
|
|||||||
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
|
||||||
).select_related('guardian', 'junior').last()
|
).select_related('guardian', 'junior').last()
|
||||||
if task_queryset:
|
if task_queryset:
|
||||||
if task_queryset.junior.is_deleted or not task_queryset.junior.is_active:
|
if task_queryset.guardian.guardian_code not in task_queryset.junior.guardian_code:
|
||||||
|
return custom_error_response(ERROR_CODE['2085'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
elif task_queryset.junior.is_deleted or not task_queryset.junior.is_active:
|
||||||
return custom_error_response(ERROR_CODE['2074'], response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE['2074'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
# use CompleteTaskSerializer serializer
|
# use CompleteTaskSerializer serializer
|
||||||
if task_queryset.task_status in [str(NUMBER['four']), str(NUMBER['five'])]:
|
elif task_queryset.task_status in [str(NUMBER['four']), str(NUMBER['five'])]:
|
||||||
"""Already request send """
|
"""Already request send """
|
||||||
return custom_error_response(ERROR_CODE['2049'], response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE['2049'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
serializer = CompleteTaskSerializer(task_queryset, data={'image': image_url}, partial=True)
|
serializer = CompleteTaskSerializer(task_queryset, data={'image': image_url}, partial=True)
|
||||||
@@ -412,7 +438,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)
|
||||||
@@ -493,7 +519,10 @@ class StartTaskAPIView(views.APIView):
|
|||||||
try:
|
try:
|
||||||
task_id = self.request.data.get('task_id')
|
task_id = self.request.data.get('task_id')
|
||||||
task_queryset = JuniorTask.objects.filter(id=task_id, junior__auth__email=self.request.user).last()
|
task_queryset = JuniorTask.objects.filter(id=task_id, junior__auth__email=self.request.user).last()
|
||||||
|
print("task_queryset==>",task_queryset)
|
||||||
if task_queryset and task_queryset.task_status == str(NUMBER['one']):
|
if task_queryset and task_queryset.task_status == str(NUMBER['one']):
|
||||||
|
if task_queryset.guardian.guardian_code not in task_queryset.junior.guardian_code:
|
||||||
|
return custom_error_response(ERROR_CODE['2083'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
# use StartTaskSerializer serializer
|
# use StartTaskSerializer serializer
|
||||||
serializer = StartTaskSerializer(task_queryset, data=request.data, partial=True)
|
serializer = StartTaskSerializer(task_queryset, data=request.data, partial=True)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
@@ -577,8 +606,8 @@ class StartAssessmentAPIView(viewsets.ModelViewSet):
|
|||||||
article_id = self.request.GET.get('article_id')
|
article_id = self.request.GET.get('article_id')
|
||||||
# if referral_code:
|
# if referral_code:
|
||||||
article = Article.objects.filter(id=article_id, is_deleted=False).prefetch_related(
|
article = Article.objects.filter(id=article_id, is_deleted=False).prefetch_related(
|
||||||
'article_cards', 'article_survey', 'article_survey__options'
|
'article_survey'
|
||||||
).order_by('-created_at')
|
)
|
||||||
return article
|
return article
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
"""Params
|
"""Params
|
||||||
@@ -615,7 +644,7 @@ class CheckAnswerAPIView(viewsets.ModelViewSet):
|
|||||||
answer_id = self.request.GET.get('answer_id')
|
answer_id = self.request.GET.get('answer_id')
|
||||||
current_page = self.request.GET.get('current_page')
|
current_page = self.request.GET.get('current_page')
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_queryset()
|
||||||
submit_ans = SurveyOption.objects.filter(id=answer_id, is_answer=True).last()
|
submit_ans = SurveyOption.objects.filter(id=answer_id).last()
|
||||||
junior_article_points = JuniorArticlePoints.objects.filter(junior__auth=self.request.user,
|
junior_article_points = JuniorArticlePoints.objects.filter(junior__auth=self.request.user,
|
||||||
question=queryset)
|
question=queryset)
|
||||||
if submit_ans:
|
if submit_ans:
|
||||||
@@ -658,6 +687,8 @@ class CompleteArticleAPIView(views.APIView):
|
|||||||
is_answer_correct=True).aggregate(
|
is_answer_correct=True).aggregate(
|
||||||
total_earn_points=Sum('earn_points'))['total_earn_points']
|
total_earn_points=Sum('earn_points'))['total_earn_points']
|
||||||
data = {"total_earn_points":total_earn_points}
|
data = {"total_earn_points":total_earn_points}
|
||||||
|
send_notification.delay(ARTICLE_REWARD_POINTS, None, None,
|
||||||
|
request.user.id, {'points': total_earn_points})
|
||||||
return custom_response(SUCCESS_CODE['3042'], data, response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3042'], 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)
|
||||||
@@ -718,26 +749,34 @@ class CreateArticleCardAPIView(viewsets.ModelViewSet):
|
|||||||
|
|
||||||
class RemoveGuardianCodeAPIView(views.APIView):
|
class RemoveGuardianCodeAPIView(views.APIView):
|
||||||
"""Remove guardian code request API
|
"""Remove guardian code request API
|
||||||
No Payload"""
|
Payload
|
||||||
|
{"guardian_code"
|
||||||
|
:"GRD037"
|
||||||
|
}"""
|
||||||
serializer_class = RemoveGuardianCodeSerializer
|
serializer_class = RemoveGuardianCodeSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
def put(self, request, format=None):
|
def put(self, request, format=None):
|
||||||
try:
|
try:
|
||||||
|
guardian_code = self.request.data.get("guardian_code")
|
||||||
|
guardian_data = Guardian.objects.filter(guardian_code=guardian_code).last()
|
||||||
junior_queryset = Junior.objects.filter(auth=self.request.user).last()
|
junior_queryset = Junior.objects.filter(auth=self.request.user).last()
|
||||||
if junior_queryset:
|
if junior_queryset:
|
||||||
# use RemoveGuardianCodeSerializer serializer
|
# use RemoveGuardianCodeSerializer serializer
|
||||||
serializer = RemoveGuardianCodeSerializer(junior_queryset, data=request.data, partial=True)
|
serializer = RemoveGuardianCodeSerializer(junior_queryset, context = {"guardian_code":guardian_code},
|
||||||
|
data=request.data, partial=True)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
# save serializer
|
# save serializer
|
||||||
serializer.save()
|
serializer.save()
|
||||||
|
JuniorGuardianRelationship.objects.filter(guardian=guardian_data, junior=junior_queryset).delete()
|
||||||
return custom_response(SUCCESS_CODE['3044'], response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3044'], 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:
|
||||||
# task in another state
|
# task in another state
|
||||||
return custom_error_response(ERROR_CODE['2047'], response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE['2047'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
error_detail = e.detail.get('error', None)
|
||||||
|
return custom_error_response(error_detail, response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
class FAQViewSet(GenericViewSet, mixins.CreateModelMixin,
|
class FAQViewSet(GenericViewSet, mixins.CreateModelMixin,
|
||||||
|
|||||||
+53
-20
@@ -6,60 +6,76 @@ ASSOCIATE_REQUEST = 3
|
|||||||
ASSOCIATE_REJECTED = 4
|
ASSOCIATE_REJECTED = 4
|
||||||
ASSOCIATE_APPROVED = 5
|
ASSOCIATE_APPROVED = 5
|
||||||
REFERRAL_POINTS = 6
|
REFERRAL_POINTS = 6
|
||||||
JUNIOR_ADDED = 7
|
ASSOCIATE_JUNIOR = 7
|
||||||
|
ASSOCIATE_EXISTING_JUNIOR = 8
|
||||||
|
|
||||||
TASK_ASSIGNED = 8
|
TASK_ASSIGNED = 9
|
||||||
TASK_ACTION = 9
|
TASK_ACTION = 10
|
||||||
TASK_REJECTED = 10
|
TASK_REJECTED = 11
|
||||||
TASK_APPROVED = 11
|
TASK_APPROVED = 12
|
||||||
PENDING_TASK_EXPIRING = 12
|
PENDING_TASK_EXPIRING = 13
|
||||||
IN_PROGRESS_TASK_EXPIRING = 13
|
IN_PROGRESS_TASK_EXPIRING = 14
|
||||||
REMOVE_JUNIOR = 15
|
TOP_JUNIOR = 15
|
||||||
|
|
||||||
|
NEW_ARTICLE_PUBLISHED = 16
|
||||||
|
ARTICLE_REWARD_POINTS = 17
|
||||||
|
REMOVE_JUNIOR = 18
|
||||||
|
|
||||||
TEST_NOTIFICATION = 99
|
TEST_NOTIFICATION = 99
|
||||||
|
# notification dictionary
|
||||||
NOTIFICATION_DICT = {
|
NOTIFICATION_DICT = {
|
||||||
REGISTRATION: {
|
REGISTRATION: {
|
||||||
"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."
|
||||||
},
|
},
|
||||||
# user will receive notification as soon junior sign up application using their guardian code
|
# user will receive notification as soon junior
|
||||||
# for association
|
# sign up application using their guardian code for association
|
||||||
ASSOCIATE_REQUEST: {
|
ASSOCIATE_REQUEST: {
|
||||||
"title": "Associate request!",
|
"title": "Associate request!",
|
||||||
"body": "You have request from {from_user} to associate with you."
|
"body": "You have request from {from_user} to associate with you."
|
||||||
},
|
},
|
||||||
# Juniors will receive notification when custodians reject their request for associate
|
# Juniors will receive notification when
|
||||||
|
# custodians reject their request for associate
|
||||||
ASSOCIATE_REJECTED: {
|
ASSOCIATE_REJECTED: {
|
||||||
"title": "Associate request rejected!",
|
"title": "Associate request rejected!",
|
||||||
"body": "Your request to associate has been rejected by {from_user}."
|
"body": "Your request to associate has been rejected by {from_user}."
|
||||||
},
|
},
|
||||||
# Juniors will receive notification when custodians approve their request for associate
|
# Juniors will receive notification when
|
||||||
|
# custodians approve their request for associate
|
||||||
ASSOCIATE_APPROVED: {
|
ASSOCIATE_APPROVED: {
|
||||||
"title": "Associate request approved!",
|
"title": "Associate request approved!",
|
||||||
"body": "Your request to associate has been approved by {from_user}."
|
"body": "Your request to associate has been approved by {from_user}."
|
||||||
},
|
},
|
||||||
# Juniors will receive Notifications for every Points earned by referrals
|
# Juniors will receive Notifications
|
||||||
|
# for every Points earned by referrals
|
||||||
REFERRAL_POINTS: {
|
REFERRAL_POINTS: {
|
||||||
"title": "Earn Referral points!",
|
"title": "Earn Referral points!",
|
||||||
"body": "You earn 5 points for referral."
|
"body": "You earn 5 points for referral."
|
||||||
},
|
},
|
||||||
# Juniors will receive notification once any custodians add them in their account
|
# Juniors will receive notification
|
||||||
JUNIOR_ADDED: {
|
# once any custodians add them in their account
|
||||||
|
ASSOCIATE_JUNIOR: {
|
||||||
"title": "Profile already setup!",
|
"title": "Profile already setup!",
|
||||||
"body": "Your guardian has already setup your profile."
|
"body": "Your guardian has already setup your profile."
|
||||||
},
|
},
|
||||||
# Juniors will receive Notification for every Task Assign by Custodians
|
ASSOCIATE_EXISTING_JUNIOR: {
|
||||||
|
"title": "Associated to guardian",
|
||||||
|
"body": "Your are associated to your guardian {from_user}."
|
||||||
|
},
|
||||||
|
# Juniors will receive Notification
|
||||||
|
# for every Task Assign by Custodians
|
||||||
TASK_ASSIGNED: {
|
TASK_ASSIGNED: {
|
||||||
"title": "New task assigned!",
|
"title": "New task assigned!",
|
||||||
"body": "{from_user} has assigned you a new task."
|
"body": "{from_user} has assigned you a new task."
|
||||||
},
|
},
|
||||||
# Guardian will receive notification as soon as junior send task for approval
|
# Guardian will receive notification as soon
|
||||||
|
# as junior send task for approval
|
||||||
TASK_ACTION: {
|
TASK_ACTION: {
|
||||||
"title": "Task completion approval!",
|
"title": "Task completion approval!",
|
||||||
"body": "{from_user} completed her task {task_name}."
|
"body": "{from_user} completed their task {task_name}."
|
||||||
},
|
},
|
||||||
# Juniors will receive notification as soon as their task is rejected by custodians
|
# Juniors will receive notification as soon
|
||||||
|
# as their task is rejected by custodians
|
||||||
TASK_REJECTED: {
|
TASK_REJECTED: {
|
||||||
"title": "Task completion rejected!",
|
"title": "Task completion rejected!",
|
||||||
"body": "Your task completion request has been rejected by {from_user}."
|
"body": "Your task completion request has been rejected by {from_user}."
|
||||||
@@ -83,6 +99,23 @@ NOTIFICATION_DICT = {
|
|||||||
"body": "{from_user} didn't take any action on assigned task {task_name} and it's expiring soon. "
|
"body": "{from_user} didn't take any action on assigned task {task_name} and it's expiring soon. "
|
||||||
"Please assist to complete it."
|
"Please assist to complete it."
|
||||||
},
|
},
|
||||||
|
# Juniors will receive Notification
|
||||||
|
# related to Leaderboard progress
|
||||||
|
TOP_JUNIOR: {
|
||||||
|
"title": "Leaderboard topper!",
|
||||||
|
"body": "{from_user} is on top in leaderboard with {points} points."
|
||||||
|
},
|
||||||
|
# Juniors will receive notification
|
||||||
|
# when admin add any new financial learnings
|
||||||
|
NEW_ARTICLE_PUBLISHED: {
|
||||||
|
"title": "Time to read!",
|
||||||
|
"body": "A new article has been published."
|
||||||
|
},
|
||||||
|
# Juniors will receive notification when they earn points by reading financial Learning
|
||||||
|
ARTICLE_REWARD_POINTS: {
|
||||||
|
"title": "Article reward points!",
|
||||||
|
"body": "You are rewarded with {points} points for reading article and answering questions. "
|
||||||
|
},
|
||||||
# Juniors will receive notification as soon as their custodians remove them from account
|
# Juniors will receive notification as soon as their custodians remove them from account
|
||||||
REMOVE_JUNIOR: {
|
REMOVE_JUNIOR: {
|
||||||
"title": "Disassociate by guardian!",
|
"title": "Disassociate by guardian!",
|
||||||
|
|||||||
+42
-8
@@ -8,6 +8,7 @@ from firebase_admin.messaging import Message, Notification as FirebaseNotificati
|
|||||||
|
|
||||||
# django imports
|
# django imports
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from account.models import UserNotification
|
from account.models import UserNotification
|
||||||
@@ -18,14 +19,13 @@ 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
|
||||||
|
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
def register_fcm_token(user_id, registration_id, device_id, device_type):
|
def register_fcm_token(user_id, registration_id, device_id, device_type):
|
||||||
""" used to register the fcm device token"""
|
""" used to register the fcm device token"""
|
||||||
device, _ = FCMDevice.objects.update_or_create(device_id=device_id,
|
device, _ = FCMDevice.objects.update_or_create(user_id=user_id,
|
||||||
defaults={'user_id': user_id, 'type': device_type,
|
defaults={'device_id': device_id, 'type': device_type,
|
||||||
'active': True,
|
'active': True,
|
||||||
'registration_id': registration_id})
|
'registration_id': registration_id})
|
||||||
return device
|
return device
|
||||||
@@ -76,20 +76,23 @@ def get_notification_data(notification_type, from_user_id, from_user_type, to_us
|
|||||||
push_data = NOTIFICATION_DICT[notification_type].copy()
|
push_data = NOTIFICATION_DICT[notification_type].copy()
|
||||||
notification_data = push_data.copy()
|
notification_data = push_data.copy()
|
||||||
task_name = None
|
task_name = None
|
||||||
|
points = extra_data.get('points', None)
|
||||||
if 'task_id' in extra_data:
|
if 'task_id' in extra_data:
|
||||||
task = JuniorTask.objects.filter(id=extra_data.get('task_id')).first()
|
task = JuniorTask.objects.filter(id=extra_data.get('task_id')).first()
|
||||||
task_name = task.task_name
|
task_name = task.task_name
|
||||||
|
extra_data['task_name'] = task_name
|
||||||
extra_data['task_image'] = task.image if task.image else task.default_image
|
extra_data['task_image'] = task.image if task.image else task.default_image
|
||||||
|
|
||||||
from_user_name, from_user_image, from_user = get_from_user_details(from_user_id, from_user_type)
|
from_user_name, from_user_image, from_user = get_from_user_details(from_user_id, from_user_type)
|
||||||
|
|
||||||
push_data['body'] = push_data['body'].format(from_user=from_user_name, task_name=task_name)
|
push_data['body'] = push_data['body'].format(from_user=from_user_name, task_name=task_name, points=points)
|
||||||
notification_data['body'] = notification_data['body'].format(from_user=from_user_name, task_name=task_name)
|
notification_data['body'] = notification_data['body'].format(from_user=from_user_name,
|
||||||
|
task_name=task_name, points=points)
|
||||||
notification_data['from_user'] = from_user_name
|
notification_data['from_user'] = from_user_name
|
||||||
notification_data['from_user_image'] = from_user_image
|
notification_data['from_user_image'] = from_user_image
|
||||||
|
|
||||||
notification_data.update(extra_data)
|
notification_data.update(extra_data)
|
||||||
to_user = User.objects.get(id=to_user_id)
|
to_user = User.objects.filter(id=to_user_id).first()
|
||||||
return notification_data, push_data, from_user, to_user
|
return notification_data, push_data, from_user, to_user
|
||||||
|
|
||||||
|
|
||||||
@@ -115,6 +118,39 @@ def send_push(user, data):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def send_multiple_push(queryset, data):
|
||||||
|
""" used to send same notification to multiple users """
|
||||||
|
FCMDevice.objects.filter(user__in=queryset, active=True).send_message(
|
||||||
|
Message(notification=FirebaseNotification(data['title'], data['body']), data=data)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task()
|
||||||
|
def send_notification_multiple_user(notification_type, from_user_id, from_user_type,
|
||||||
|
extra_data: dict = {}):
|
||||||
|
"""
|
||||||
|
used to send notification to multiple user for the given notification type
|
||||||
|
"""
|
||||||
|
to_user_list = User.objects.filter(junior_profile__is_verified=True, is_superuser=False
|
||||||
|
).exclude(junior_profile__isnull=True, guardian_profile__isnull=True)
|
||||||
|
|
||||||
|
notification_data, push_data, from_user, _ = get_notification_data(notification_type, from_user_id,
|
||||||
|
from_user_type, None, extra_data)
|
||||||
|
|
||||||
|
notification_list = []
|
||||||
|
for user in to_user_list:
|
||||||
|
notification_copy_data = notification_data.copy()
|
||||||
|
notification_copy_data.update(
|
||||||
|
{'badge': Notification.objects.filter(notification_to=user, is_read=False).count()})
|
||||||
|
notification_list.append(Notification(notification_type=notification_type,
|
||||||
|
notification_to=user,
|
||||||
|
notification_from=from_user,
|
||||||
|
data=notification_copy_data))
|
||||||
|
Notification.objects.bulk_create(notification_list)
|
||||||
|
to_user_list = to_user_list.filter(user_notification__push_notification=True)
|
||||||
|
send_multiple_push(to_user_list, push_data)
|
||||||
|
|
||||||
|
|
||||||
@shared_task()
|
@shared_task()
|
||||||
def send_notification_to_guardian(notification_type, from_user_id, to_user_id, extra_data):
|
def send_notification_to_guardian(notification_type, from_user_id, to_user_id, extra_data):
|
||||||
"""
|
"""
|
||||||
@@ -143,5 +179,3 @@ def send_notification_to_junior(notification_type, from_user_id, to_user_id, ext
|
|||||||
from_user = Guardian.objects.filter(user_id=from_user_id).first()
|
from_user = Guardian.objects.filter(user_id=from_user_id).first()
|
||||||
extra_data['from_user_image'] = from_user.image
|
extra_data['from_user_image'] = from_user.image
|
||||||
send_notification(notification_type, from_user_id, to_user_id, extra_data)
|
send_notification(notification_type, from_user_id, to_user_id, extra_data)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+5
-12
@@ -11,7 +11,7 @@ from rest_framework import viewsets, status, views
|
|||||||
# local imports
|
# local imports
|
||||||
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 base.tasks import notify_task_expiry
|
from base.tasks import notify_task_expiry, notify_top_junior
|
||||||
from notifications.constants import TEST_NOTIFICATION
|
from notifications.constants import TEST_NOTIFICATION
|
||||||
from notifications.serializers import RegisterDevice, NotificationListSerializer, ReadNotificationSerializer
|
from notifications.serializers import RegisterDevice, NotificationListSerializer, ReadNotificationSerializer
|
||||||
from notifications.utils import send_notification
|
from notifications.utils import send_notification
|
||||||
@@ -36,7 +36,7 @@ class NotificationViewSet(viewsets.GenericViewSet):
|
|||||||
paginator = self.pagination_class()
|
paginator = self.pagination_class()
|
||||||
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, count=queryset.count())
|
||||||
|
|
||||||
@action(methods=['post'], detail=False, url_path='device', url_name='device', serializer_class=RegisterDevice)
|
@action(methods=['post'], detail=False, url_path='device', url_name='device', serializer_class=RegisterDevice)
|
||||||
def fcm_registration(self, request):
|
def fcm_registration(self, request):
|
||||||
@@ -52,9 +52,11 @@ class NotificationViewSet(viewsets.GenericViewSet):
|
|||||||
@action(methods=['get'], detail=False, url_path='test', url_name='test')
|
@action(methods=['get'], detail=False, url_path='test', url_name='test')
|
||||||
def send_test_notification(self, request):
|
def send_test_notification(self, request):
|
||||||
"""
|
"""
|
||||||
to send test notification
|
to test send notification, task expiry, top junior
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
notify_task_expiry()
|
||||||
|
notify_top_junior()
|
||||||
send_notification(TEST_NOTIFICATION, None, None, request.auth.payload['user_id'],
|
send_notification(TEST_NOTIFICATION, None, None, request.auth.payload['user_id'],
|
||||||
{})
|
{})
|
||||||
return custom_response(SUCCESS_CODE["3000"])
|
return custom_response(SUCCESS_CODE["3000"])
|
||||||
@@ -67,12 +69,3 @@ class NotificationViewSet(viewsets.GenericViewSet):
|
|||||||
"""
|
"""
|
||||||
Notification.objects.filter(id__in=request.data.get('id')).update(is_read=True)
|
Notification.objects.filter(id__in=request.data.get('id')).update(is_read=True)
|
||||||
return custom_response(SUCCESS_CODE['3039'], response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3039'], response_status=status.HTTP_200_OK)
|
||||||
|
|
||||||
@action(methods=['get'], url_path='task', url_name='task', detail=False,
|
|
||||||
permission_classes=[AllowAny])
|
|
||||||
def task(self, request, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
notification list
|
|
||||||
"""
|
|
||||||
notify_task_expiry()
|
|
||||||
return custom_response(SUCCESS_CODE['3039'], response_status=status.HTTP_200_OK)
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from django.contrib.auth import get_user_model
|
|||||||
|
|
||||||
from account.utils import get_user_full_name
|
from account.utils import get_user_full_name
|
||||||
# local imports
|
# local imports
|
||||||
from base.constants import USER_TYPE
|
from base.constants import USER_TYPE, JUNIOR
|
||||||
|
|
||||||
from junior.models import JuniorPoints, Junior
|
from junior.models import JuniorPoints, Junior
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ class JuniorLeaderboardSerializer(serializers.ModelSerializer):
|
|||||||
:param obj: junior object
|
:param obj: junior object
|
||||||
:return: full name
|
:return: full name
|
||||||
"""
|
"""
|
||||||
return f"{obj.auth.first_name} {obj.auth.last_name}" if obj.auth.last_name else obj.auth.first_name
|
return get_user_full_name(obj.auth)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_first_name(obj):
|
def get_first_name(obj):
|
||||||
@@ -60,6 +60,8 @@ class LeaderboardSerializer(serializers.ModelSerializer):
|
|||||||
"""
|
"""
|
||||||
leaderboard serializer
|
leaderboard serializer
|
||||||
"""
|
"""
|
||||||
|
user_id = serializers.SerializerMethodField()
|
||||||
|
user_type = serializers.SerializerMethodField()
|
||||||
junior = JuniorLeaderboardSerializer()
|
junior = JuniorLeaderboardSerializer()
|
||||||
rank = serializers.IntegerField()
|
rank = serializers.IntegerField()
|
||||||
|
|
||||||
@@ -68,7 +70,15 @@ class LeaderboardSerializer(serializers.ModelSerializer):
|
|||||||
meta class
|
meta class
|
||||||
"""
|
"""
|
||||||
model = JuniorPoints
|
model = JuniorPoints
|
||||||
fields = ('total_points', 'rank', 'junior')
|
fields = ('user_id', 'user_type', 'total_points', 'rank', 'junior')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_user_id(obj):
|
||||||
|
return obj.junior.auth.id
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_user_type(obj):
|
||||||
|
return JUNIOR
|
||||||
|
|
||||||
|
|
||||||
class UserCSVReportSerializer(serializers.ModelSerializer):
|
class UserCSVReportSerializer(serializers.ModelSerializer):
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ from base.constants import (ARTICLE_SURVEY_POINTS, MAX_ARTICLE_CARD, MIN_ARTICLE
|
|||||||
# local imports
|
# local imports
|
||||||
from base.messages import ERROR_CODE
|
from base.messages import ERROR_CODE
|
||||||
from guardian.utils import upload_image_to_alibaba
|
from guardian.utils import upload_image_to_alibaba
|
||||||
|
from notifications.constants import NEW_ARTICLE_PUBLISHED
|
||||||
|
from notifications.utils import send_notification_multiple_user
|
||||||
from web_admin.models import Article, ArticleCard, SurveyOption, ArticleSurvey, DefaultArticleCardImage
|
from web_admin.models import Article, ArticleCard, SurveyOption, ArticleSurvey, DefaultArticleCardImage
|
||||||
from web_admin.utils import pop_id, get_image_url
|
from web_admin.utils import pop_id, get_image_url
|
||||||
from junior.models import JuniorArticlePoints, JuniorArticle
|
from junior.models import JuniorArticlePoints, JuniorArticle
|
||||||
@@ -119,11 +121,15 @@ class ArticleSerializer(serializers.ModelSerializer):
|
|||||||
option = pop_id(option)
|
option = pop_id(option)
|
||||||
SurveyOption.objects.create(survey=survey_obj, **option)
|
SurveyOption.objects.create(survey=survey_obj, **option)
|
||||||
|
|
||||||
|
# All juniors will receive notification when admin add any new financial learnings/article
|
||||||
|
send_notification_multiple_user.delay(NEW_ARTICLE_PUBLISHED, None, None, {})
|
||||||
|
|
||||||
return article
|
return article
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
"""
|
"""
|
||||||
to update article and related table
|
to update article and related table
|
||||||
|
:param validated_data:
|
||||||
:param instance: article object,
|
:param instance: article object,
|
||||||
:return: article object
|
:return: article object
|
||||||
"""
|
"""
|
||||||
@@ -219,8 +225,7 @@ class ArticleListSerializer(serializers.ModelSerializer):
|
|||||||
"""
|
"""
|
||||||
serializer for article API
|
serializer for article API
|
||||||
"""
|
"""
|
||||||
article_cards = ArticleCardSerializer(many=True)
|
image = serializers.SerializerMethodField('get_image')
|
||||||
article_survey = ArticleSurveySerializer(many=True)
|
|
||||||
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')
|
||||||
|
|
||||||
@@ -229,12 +234,16 @@ class ArticleListSerializer(serializers.ModelSerializer):
|
|||||||
meta class
|
meta class
|
||||||
"""
|
"""
|
||||||
model = Article
|
model = Article
|
||||||
fields = ('id', 'title', 'description', 'article_cards', 'article_survey', 'total_points', 'is_completed')
|
fields = ('id', 'title', 'description','image', 'total_points', 'is_completed')
|
||||||
|
|
||||||
|
def get_image(self, obj):
|
||||||
|
"""article image"""
|
||||||
|
if obj.article_cards.first():
|
||||||
|
return obj.article_cards.first().image_url
|
||||||
|
return None
|
||||||
def get_total_points(self, obj):
|
def get_total_points(self, obj):
|
||||||
"""total points of article"""
|
"""total points of article"""
|
||||||
total_question = ArticleSurvey.objects.filter(article=obj).count()
|
return obj.article_survey.all().count() * NUMBER['five']
|
||||||
return total_question * NUMBER['five']
|
|
||||||
|
|
||||||
def get_is_completed(self, obj):
|
def get_is_completed(self, obj):
|
||||||
"""complete all question"""
|
"""complete all question"""
|
||||||
@@ -268,14 +277,14 @@ class ArticleQuestionSerializer(serializers.ModelSerializer):
|
|||||||
ans_obj = SurveyOption.objects.filter(survey=obj, is_answer=True).last()
|
ans_obj = SurveyOption.objects.filter(survey=obj, is_answer=True).last()
|
||||||
if ans_obj:
|
if ans_obj:
|
||||||
return ans_obj.id
|
return ans_obj.id
|
||||||
return str("None")
|
return None
|
||||||
|
|
||||||
def get_attempted_answer(self, obj):
|
def get_attempted_answer(self, obj):
|
||||||
"""attempt question or not"""
|
"""attempt question or not"""
|
||||||
context_data = self.context.get('user')
|
context_data = self.context.get('user')
|
||||||
junior_article_obj = JuniorArticlePoints.objects.filter(junior__auth=context_data,
|
junior_article_obj = JuniorArticlePoints.objects.filter(junior__auth=context_data,
|
||||||
question=obj, is_answer_correct=True).last()
|
question=obj).last()
|
||||||
if junior_article_obj:
|
if junior_article_obj and junior_article_obj.submitted_answer:
|
||||||
return junior_article_obj.submitted_answer.id
|
return junior_article_obj.submitted_answer.id
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -297,8 +306,9 @@ class StartAssessmentSerializer(serializers.ModelSerializer):
|
|||||||
"""current page"""
|
"""current page"""
|
||||||
context_data = self.context.get('user')
|
context_data = self.context.get('user')
|
||||||
data = JuniorArticle.objects.filter(junior__auth=context_data, article=obj).last()
|
data = JuniorArticle.objects.filter(junior__auth=context_data, article=obj).last()
|
||||||
|
total_count = obj.article_survey.all().count()
|
||||||
if data:
|
if data:
|
||||||
return data.current_que_page
|
return data.current_que_page if data.current_que_page < total_count else data.current_que_page - 1
|
||||||
return NUMBER['zero']
|
return NUMBER['zero']
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -128,10 +128,12 @@ class AnalyticsViewSet(GenericViewSet):
|
|||||||
:param request:
|
:param request:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
queryset = JuniorPoints.objects.prefetch_related('junior', 'junior__auth').annotate(rank=Window(
|
queryset = JuniorPoints.objects.filter(
|
||||||
expression=Rank(),
|
junior__is_verified=True
|
||||||
order_by=[F('total_points').desc(), 'junior__created_at']
|
).select_related('junior', 'junior__auth').annotate(rank=Window(
|
||||||
)).order_by('-total_points', 'junior__created_at')
|
expression=Rank(),
|
||||||
|
order_by=[F('total_points').desc(), 'junior__created_at']
|
||||||
|
)).order_by('-total_points', 'junior__created_at')
|
||||||
paginator = CustomPageNumberPagination()
|
paginator = CustomPageNumberPagination()
|
||||||
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)
|
||||||
@@ -199,10 +201,12 @@ class AnalyticsViewSet(GenericViewSet):
|
|||||||
|
|
||||||
# sheet 3 for Juniors Leaderboard and rank
|
# sheet 3 for Juniors Leaderboard and rank
|
||||||
elif sheet_name == 'Juniors Leaderboard':
|
elif sheet_name == 'Juniors Leaderboard':
|
||||||
queryset = JuniorPoints.objects.prefetch_related('junior', 'junior__auth').annotate(rank=Window(
|
queryset = JuniorPoints.objects.filter(
|
||||||
expression=Rank(),
|
junior__is_verified=True
|
||||||
order_by=[F('total_points').desc(), 'junior__created_at']
|
).select_related('junior', 'junior__auth').annotate(rank=Window(
|
||||||
)).order_by('-total_points', 'junior__created_at')[:15]
|
expression=Rank(),
|
||||||
|
order_by=[F('total_points').desc(), 'junior__created_at']
|
||||||
|
)).order_by('-total_points', 'junior__created_at')[:15]
|
||||||
df_leaderboard = pd.DataFrame([
|
df_leaderboard = pd.DataFrame([
|
||||||
{
|
{
|
||||||
'Name': get_user_full_name(junior.junior.auth),
|
'Name': get_user_full_name(junior.junior.auth),
|
||||||
|
|||||||
@@ -229,10 +229,7 @@ class ArticleListViewSet(GenericViewSet, mixins.ListModelMixin):
|
|||||||
http_method_names = ['get',]
|
http_method_names = ['get',]
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
article = self.queryset.objects.filter(is_deleted=False, is_published=True).prefetch_related(
|
queryset = self.queryset.objects.filter(is_deleted=False, is_published=True).order_by('-created_at')
|
||||||
'article_cards', 'article_survey', 'article_survey__options'
|
|
||||||
).order_by('-created_at')
|
|
||||||
queryset = self.filter_queryset(article)
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
|
|||||||
@@ -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'])
|
||||||
|
|||||||
+10
-12
@@ -27,10 +27,19 @@ app.config_from_object('django.conf:settings')
|
|||||||
# Load task modules from all registered Django apps.
|
# Load task modules from all registered Django apps.
|
||||||
app.autodiscover_tasks()
|
app.autodiscover_tasks()
|
||||||
|
|
||||||
|
# scheduled task
|
||||||
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='0', hour='18'),
|
||||||
|
},
|
||||||
|
'notify_top_junior': {
|
||||||
|
'task': 'base.tasks.notify_top_junior',
|
||||||
|
'schedule': crontab(minute='0', hour='*/2'),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,14 +48,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),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user