mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2026-03-10 20:31:45 +00:00
Compare commits
89 Commits
ZBKBCK-346
...
ZBKBCK-47
| Author | SHA1 | Date | |
|---|---|---|---|
| 3072bd5cdb | |||
| 930b58cf05 | |||
| cd3b385756 | |||
| f541608656 | |||
| 5b9f7b1828 | |||
| 89dda61bff | |||
| 31f071a463 | |||
| 20644a6293 | |||
| a8b01d4c3a | |||
| 56e1484b87 | |||
| 557a7d7a5c | |||
| 4e0c6a91f4 | |||
| f931e20334 | |||
| 8d159ac3a4 | |||
| 95ce57ec7d | |||
| 7068551050 | |||
| c23d65f67c | |||
| 73f05dc843 | |||
| 290089b9ef | |||
| 5f3a9c35fa | |||
| b92115168d | |||
| 19acef10ef | |||
| 05fd76a50b | |||
| 60e6d96379 | |||
| fad39d399f | |||
| d573d56a35 | |||
| 08a08960ee | |||
| f8e529600b | |||
| 9765c90b9b | |||
| 930c10b578 | |||
| 8ca74e4b03 | |||
| 95dad86b12 | |||
| dfff643c71 | |||
| 214566ec8f | |||
| 210e1a39e9 | |||
| e380f3f6ab | |||
| 99a59162a2 | |||
| 67a5f670f8 | |||
| 82189d3953 | |||
| 65ecd9a125 | |||
| a7bce32993 | |||
| 4495d8999c | |||
| 61e94c9469 | |||
| 1c3d4731c1 | |||
| 46853011be | |||
| 2216411fd2 | |||
| 606c1fa6e6 | |||
| 092cbfad3e | |||
| 249a469d89 | |||
| d202774df1 | |||
| 1adf0c2f70 | |||
| b193166914 | |||
| 48b455e38a | |||
| 6d54a718b9 | |||
| e84180a6c2 | |||
| 92e5104e3f | |||
| ed1b5dd453 | |||
| 74328f37b2 | |||
| d8f4467d98 | |||
| a9cc05c675 | |||
| 83d7d119be | |||
| 19a6475097 | |||
| 4ca60af5da | |||
| 807526acfa | |||
| f4149379c2 | |||
| b8f1acaed8 | |||
| 9e5dd5e3d5 | |||
| b961044e4d | |||
| 2498394127 | |||
| 2fc65d462d | |||
| cdf656fdad | |||
| 8eaf8751c2 | |||
| 6867920754 | |||
| 22ba4288d9 | |||
| 7ab16cb3de | |||
| 07d150309b | |||
| 3801e6e027 | |||
| e89fc513cb | |||
| e1af1c200d | |||
| b238379a22 | |||
| c081bc621d | |||
| d2c8b18e3f | |||
| bdc0ba4fd5 | |||
| 3af2584d6a | |||
| 62cf2b14bf | |||
| cbd3d139a5 | |||
| 7cb792c6cf | |||
| 5ea28bbd75 | |||
| 180104ece8 |
@ -2,7 +2,7 @@
|
||||
from django.contrib import admin
|
||||
|
||||
"""Import django app"""
|
||||
from .models import UserEmailOtp, DefaultTaskImages, UserNotification, UserDelete, UserDeviceDetails
|
||||
from .models import UserEmailOtp, DefaultTaskImages, UserNotification, UserDelete, UserDeviceDetails, ForceUpdate
|
||||
# Register your models here.
|
||||
|
||||
@admin.register(UserDelete)
|
||||
@ -39,6 +39,19 @@ class UserEmailOtpAdmin(admin.ModelAdmin):
|
||||
"""Return object in email and otp format"""
|
||||
return self.email + '-' + self.otp
|
||||
|
||||
@admin.register(ForceUpdate)
|
||||
class ForceUpdateAdmin(admin.ModelAdmin):
|
||||
"""Force update"""
|
||||
list_display = ['version', 'device_type']
|
||||
readonly_fields = ('device_type',)
|
||||
|
||||
def has_add_permission(self, request):
|
||||
count = ForceUpdate.objects.all().count()
|
||||
if count < 2:
|
||||
return True
|
||||
return False
|
||||
def has_delete_permission(self, request, obj=None):
|
||||
return False
|
||||
@admin.register(UserDeviceDetails)
|
||||
class UserDeviceDetailsAdmin(admin.ModelAdmin):
|
||||
"""User profile admin"""
|
||||
|
||||
@ -5,7 +5,7 @@ from rest_framework.response import Response
|
||||
from rest_framework.renderers import JSONRenderer
|
||||
"""App django"""
|
||||
from account.utils import custom_error_response
|
||||
from account.models import UserDeviceDetails
|
||||
from account.models import UserDeviceDetails, ForceUpdate
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||
from base.constants import NUMBER
|
||||
from junior.models import Junior
|
||||
@ -18,9 +18,9 @@ from guardian.models import Guardian
|
||||
# user can login in single
|
||||
# device at a time"""
|
||||
|
||||
def custom_response(custom_error):
|
||||
def custom_response(custom_error, response_status = status.HTTP_404_NOT_FOUND):
|
||||
"""custom response"""
|
||||
response = Response(custom_error.data, status=status.HTTP_404_NOT_FOUND)
|
||||
response = Response(custom_error.data, status=response_status)
|
||||
# Set content type header to "application/json"
|
||||
response['Content-Type'] = 'application/json'
|
||||
# Render the response as JSON
|
||||
@ -39,6 +39,9 @@ class CustomMiddleware(object):
|
||||
# Code to be executed after the view is called
|
||||
device_id = request.META.get('HTTP_DEVICE_ID')
|
||||
user_type = request.META.get('HTTP_USER_TYPE')
|
||||
version = request.META.get('HTTP_VERSION')
|
||||
device_type = str(request.META.get('HTTP_TYPE'))
|
||||
|
||||
api_endpoint = request.path
|
||||
if request.user.is_authenticated:
|
||||
# device details
|
||||
@ -56,4 +59,10 @@ class CustomMiddleware(object):
|
||||
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)
|
||||
response = custom_response(custom_error)
|
||||
force_update = ForceUpdate.objects.filter(version=version, device_type=device_type).last()
|
||||
api_endpoint_checks = not any(endpoint in api_endpoint for endpoint in ['/admin/', '/api/v1/admin/'])
|
||||
if not force_update and version and device_type:
|
||||
custom_error = custom_error_response(ERROR_CODE['2079'],
|
||||
response_status=status.HTTP_308_PERMANENT_REDIRECT)
|
||||
response = custom_response(custom_error, status.HTTP_308_PERMANENT_REDIRECT)
|
||||
return response
|
||||
|
||||
28
account/migrations/0010_forceupdate.py
Normal file
28
account/migrations/0010_forceupdate.py
Normal file
@ -0,0 +1,28 @@
|
||||
# Generated by Django 4.2.2 on 2023-08-22 07:39
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('account', '0009_alter_userdevicedetails_device_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ForceUpdate',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('version', models.CharField(blank=True, max_length=50, null=True)),
|
||||
('device_type', models.CharField(blank=True, choices=[('1', 'android'), ('2', 'ios')], default=None, max_length=15, null=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Force Update Version',
|
||||
'verbose_name_plural': 'Force Update Version',
|
||||
'db_table': 'force_update',
|
||||
},
|
||||
),
|
||||
]
|
||||
@ -2,8 +2,9 @@
|
||||
"""Django import"""
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ValidationError
|
||||
"""App import"""
|
||||
from base.constants import USER_TYPE
|
||||
from base.constants import USER_TYPE, DEVICE_TYPE
|
||||
# Create your models here.
|
||||
|
||||
class UserProfile(models.Model):
|
||||
@ -165,3 +166,25 @@ class UserDeviceDetails(models.Model):
|
||||
|
||||
def __str__(self):
|
||||
return self.user.email
|
||||
|
||||
|
||||
|
||||
|
||||
class ForceUpdate(models.Model):
|
||||
"""
|
||||
Force update
|
||||
"""
|
||||
"""Version ID"""
|
||||
version = models.CharField(max_length=50, null=True, blank=True)
|
||||
device_type = models.CharField(max_length=15, choices=DEVICE_TYPE, null=True, blank=True, default=None)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta(object):
|
||||
""" Meta information """
|
||||
db_table = 'force_update'
|
||||
verbose_name = 'Force Update Version'
|
||||
verbose_name_plural = 'Force Update Version'
|
||||
|
||||
def __str__(self):
|
||||
return self.version
|
||||
|
||||
@ -18,7 +18,7 @@ import secrets
|
||||
|
||||
from guardian.models import Guardian
|
||||
from junior.models import Junior
|
||||
from account.models import UserEmailOtp, DefaultTaskImages, UserDelete, UserNotification, UserPhoneOtp
|
||||
from account.models import UserEmailOtp, DefaultTaskImages, UserDelete, UserNotification, UserPhoneOtp, ForceUpdate
|
||||
from base.constants import GUARDIAN, JUNIOR, SUPERUSER, NUMBER
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE, STATUS_CODE_ERROR
|
||||
from .utils import delete_user_account_condition_social, delete_user_account_condition
|
||||
@ -308,7 +308,7 @@ class EmailVerificationSerializer(serializers.ModelSerializer):
|
||||
class Meta(object):
|
||||
"""Meta info"""
|
||||
model = UserEmailOtp
|
||||
fields = '__all__'
|
||||
fields = ('email',)
|
||||
|
||||
|
||||
|
||||
@ -390,3 +390,11 @@ class UserPhoneOtpSerializer(serializers.ModelSerializer):
|
||||
"""Meta info"""
|
||||
model = UserPhoneOtp
|
||||
fields = '__all__'
|
||||
|
||||
class ForceUpdateSerializer(serializers.ModelSerializer):
|
||||
# ForceUpdate Serializer
|
||||
|
||||
class Meta(object):
|
||||
""" meta info """
|
||||
model = ForceUpdate
|
||||
fields = ('id', 'version', 'device_type')
|
||||
|
||||
@ -29,7 +29,7 @@ from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVer
|
||||
GoogleLoginViewSet, SigninWithApple, ProfileAPIViewSet, UploadImageAPIViewSet,
|
||||
DefaultImageAPIViewSet, DeleteUserProfileAPIViewSet, UserNotificationAPIViewSet,
|
||||
UpdateUserNotificationAPIViewSet, SendSupportEmail, LogoutAPIView, AccessTokenAPIView,
|
||||
AdminLoginViewSet)
|
||||
AdminLoginViewSet, ForceUpdateViewSet)
|
||||
"""Router"""
|
||||
router = routers.SimpleRouter()
|
||||
|
||||
@ -39,8 +39,6 @@ router.register('user', UserLogin, basename='user')
|
||||
router.register('admin', AdminLoginViewSet, basename='admin')
|
||||
"""google login end point"""
|
||||
router.register('google-login', GoogleLoginViewSet, basename='admin')
|
||||
router.register('send-phone-otp', SendPhoneOtp, basename='send-phone-otp')
|
||||
router.register('user-phone-verification', UserPhoneVerification, basename='user-phone-verification')
|
||||
"""email verification end point"""
|
||||
router.register('user-email-verification', UserEmailVerification, basename='user-email-verification')
|
||||
"""Resend email otp end point"""
|
||||
@ -57,6 +55,8 @@ router.register('delete', DeleteUserProfileAPIViewSet, basename='delete')
|
||||
router.register('user-notification', UserNotificationAPIViewSet, basename='user-notification')
|
||||
"""update user account notification"""
|
||||
router.register('update-user-notification', UpdateUserNotificationAPIViewSet, basename='update-user-notification')
|
||||
# Force update entry API
|
||||
router.register('force-update', ForceUpdateViewSet, basename='force-update')
|
||||
"""Define url pattern"""
|
||||
urlpatterns = [
|
||||
path('api/v1/', include(router.urls)),
|
||||
|
||||
@ -204,8 +204,12 @@ def custom_error_response(detail, response_status):
|
||||
if not detail:
|
||||
"""when details is empty"""
|
||||
detail = {}
|
||||
return Response({"error": detail, "status": "failed", "code": response_status})
|
||||
|
||||
if response_status == 406:
|
||||
return Response({"error": detail, "status": "failed", "code": response_status,},
|
||||
status=status.HTTP_308_PERMANENT_REDIRECT)
|
||||
else:
|
||||
return Response({"error": detail, "status": "failed", "code": response_status},
|
||||
status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def get_user_data(attrs):
|
||||
"""
|
||||
@ -278,8 +282,9 @@ def generate_code(value, user_id):
|
||||
|
||||
OTP_EXPIRY = timezone.now() + timezone.timedelta(days=1)
|
||||
|
||||
|
||||
def get_user_full_name(user_obj):
|
||||
"""
|
||||
to get user's full name
|
||||
"""
|
||||
return f"{user_obj.first_name} {user_obj.last_name}" if user_obj.last_name else user_obj.first_name
|
||||
return f"{user_obj.first_name} {user_obj.last_name}" if user_obj.first_name or user_obj.last_name else "User"
|
||||
|
||||
206
account/views.py
206
account/views.py
@ -4,6 +4,7 @@ import threading
|
||||
from notifications.utils import remove_fcm_token
|
||||
|
||||
# django imports
|
||||
from rest_framework.viewsets import GenericViewSet, mixins
|
||||
from datetime import datetime, timedelta
|
||||
from rest_framework import viewsets, status, views
|
||||
from rest_framework.decorators import action
|
||||
@ -26,14 +27,15 @@ from django.conf import settings
|
||||
from guardian.models import Guardian
|
||||
from junior.models import Junior, JuniorPoints
|
||||
from guardian.utils import upload_image_to_alibaba
|
||||
from account.models import UserDeviceDetails, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification
|
||||
from account.models import (UserDeviceDetails, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification,
|
||||
ForceUpdate)
|
||||
from django.contrib.auth.models import User
|
||||
from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer,
|
||||
ForgotPasswordSerializer, ResetPasswordSerializer, ChangePasswordSerializer,
|
||||
GoogleLoginSerializer, UpdateGuardianImageSerializer, UpdateJuniorProfileImageSerializer,
|
||||
DefaultTaskImagesSerializer, DefaultTaskImagesDetailsSerializer, UserDeleteSerializer,
|
||||
UserNotificationSerializer, UpdateUserNotificationSerializer, UserPhoneOtpSerializer,
|
||||
AdminLoginSerializer)
|
||||
AdminLoginSerializer, ForceUpdateSerializer)
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||
from base.constants import NUMBER, ZOD, JUN, GRD, USER_TYPE_FLAG
|
||||
@ -49,7 +51,8 @@ class GoogleLoginMixin(object):
|
||||
def google_login(request):
|
||||
"""google login function"""
|
||||
access_token = request.data.get('access_token')
|
||||
user_type = request.data.get('user_type')
|
||||
user_type = request.META.get('HTTP_USER_TYPE')
|
||||
device_id = request.META.get('HTTP_DEVICE_ID')
|
||||
if not access_token:
|
||||
return Response({'error': 'Access token is required.'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
@ -82,14 +85,29 @@ class GoogleLoginMixin(object):
|
||||
if user_data.exists():
|
||||
if str(user_type) == '1':
|
||||
junior_query = Junior.objects.filter(auth=user_data.last()).last()
|
||||
if not junior_query:
|
||||
return custom_error_response(
|
||||
ERROR_CODE["2071"],
|
||||
response_status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
serializer = JuniorSerializer(junior_query)
|
||||
if str(user_type) == '2':
|
||||
elif str(user_type) == '2':
|
||||
guardian_query = Guardian.objects.filter(user=user_data.last()).last()
|
||||
if not guardian_query:
|
||||
return custom_error_response(
|
||||
ERROR_CODE["2070"],
|
||||
response_status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
serializer = GuardianSerializer(guardian_query)
|
||||
else:
|
||||
return custom_error_response(
|
||||
ERROR_CODE["2069"],
|
||||
response_status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
return custom_response(SUCCESS_CODE['3003'], serializer.data,
|
||||
response_status=status.HTTP_200_OK)
|
||||
|
||||
if not User.objects.filter(email__iexact=email).exists():
|
||||
else:
|
||||
user_obj = User.objects.create(username=email, email=email, first_name=first_name, last_name=last_name)
|
||||
if str(user_type) == '1':
|
||||
junior_query = Junior.objects.create(auth=user_obj, is_verified=True, is_active=True,
|
||||
@ -100,13 +118,23 @@ class GoogleLoginMixin(object):
|
||||
serializer = JuniorSerializer(junior_query)
|
||||
position = Junior.objects.all().count()
|
||||
JuniorPoints.objects.create(junior=junior_query, position=position)
|
||||
if str(user_type) == '2':
|
||||
elif str(user_type) == '2':
|
||||
guardian_query = Guardian.objects.create(user=user_obj, is_verified=True, is_active=True,
|
||||
image=profile_picture,signup_method='2',
|
||||
guardian_code=generate_code(GRD, user_obj.id),
|
||||
referral_code=generate_code(ZOD, user_obj.id)
|
||||
)
|
||||
serializer = GuardianSerializer(guardian_query)
|
||||
else:
|
||||
user_obj.delete()
|
||||
return custom_error_response(
|
||||
ERROR_CODE["2069"],
|
||||
response_status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
device_detail, created = UserDeviceDetails.objects.get_or_create(user=user_obj)
|
||||
if device_detail:
|
||||
device_detail.device_id = device_id
|
||||
device_detail.save()
|
||||
# Return a JSON response with the user's email and name
|
||||
return custom_response(SUCCESS_CODE['3003'], serializer.data,
|
||||
response_status=status.HTTP_200_OK)
|
||||
@ -117,16 +145,26 @@ class GoogleLoginViewSet(GoogleLoginMixin, viewsets.GenericViewSet):
|
||||
serializer_class = GoogleLoginSerializer
|
||||
|
||||
def create(self, request):
|
||||
"""create method"""
|
||||
"""Payload
|
||||
{
|
||||
"access_token",
|
||||
"user_type": "1"
|
||||
}"""
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
return self.google_login(request)
|
||||
|
||||
class SigninWithApple(views.APIView):
|
||||
"""This API is for sign in with Apple for app."""
|
||||
"""This API is for sign in with Apple for app.
|
||||
Payload
|
||||
{
|
||||
"access_token",
|
||||
"user_type": "1"
|
||||
}"""
|
||||
def post(self, request):
|
||||
token = request.data.get("access_token")
|
||||
user_type = request.data.get("user_type")
|
||||
user_type = request.META.get('HTTP_USER_TYPE')
|
||||
device_id = request.META.get('HTTP_DEVICE_ID')
|
||||
try:
|
||||
decoded_data = jwt.decode(token, options={"verify_signature": False})
|
||||
user_data = {"email": decoded_data.get('email'), "username": decoded_data.get('email'), "is_active": True}
|
||||
@ -134,11 +172,26 @@ class SigninWithApple(views.APIView):
|
||||
try:
|
||||
user = User.objects.get(email=decoded_data.get("email"))
|
||||
if str(user_type) == '1':
|
||||
junior_query = Junior.objects.filter(auth=user).last()
|
||||
serializer = JuniorSerializer(junior_query)
|
||||
if str(user_type) == '2':
|
||||
guardian_query = Guardian.objects.filter(user=user).last()
|
||||
serializer = GuardianSerializer(guardian_query)
|
||||
junior_data = Junior.objects.filter(auth=user).last()
|
||||
if not junior_data:
|
||||
return custom_error_response(
|
||||
ERROR_CODE["2071"],
|
||||
response_status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
serializer = JuniorSerializer(junior_data)
|
||||
elif str(user_type) == '2':
|
||||
guardian_data = Guardian.objects.filter(user=user).last()
|
||||
if not guardian_data:
|
||||
return custom_error_response(
|
||||
ERROR_CODE["2070"],
|
||||
response_status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
serializer = GuardianSerializer(guardian_data)
|
||||
else:
|
||||
return custom_error_response(
|
||||
ERROR_CODE["2069"],
|
||||
response_status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
return custom_response(SUCCESS_CODE['3003'], serializer.data,
|
||||
response_status=status.HTTP_200_OK)
|
||||
|
||||
@ -152,12 +205,22 @@ class SigninWithApple(views.APIView):
|
||||
serializer = JuniorSerializer(junior_query)
|
||||
position = Junior.objects.all().count()
|
||||
JuniorPoints.objects.create(junior=junior_query, position=position)
|
||||
if str(user_type) == '2':
|
||||
elif str(user_type) == '2':
|
||||
guardian_query = Guardian.objects.create(user=user, is_verified=True, is_active=True,
|
||||
signup_method='3',
|
||||
guardian_code=generate_code(GRD, user.id),
|
||||
referral_code=generate_code(ZOD, user.id))
|
||||
serializer = GuardianSerializer(guardian_query)
|
||||
else:
|
||||
user.delete()
|
||||
return custom_error_response(
|
||||
ERROR_CODE["2069"],
|
||||
response_status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
device_detail, created = UserDeviceDetails.objects.get_or_create(user=user)
|
||||
if device_detail:
|
||||
device_detail.device_id = device_id
|
||||
device_detail.save()
|
||||
return custom_response(SUCCESS_CODE['3003'], serializer.data,
|
||||
response_status=status.HTTP_200_OK)
|
||||
except Exception as e:
|
||||
@ -202,6 +265,10 @@ class ChangePasswordAPIView(views.APIView):
|
||||
def post(self, request):
|
||||
"""
|
||||
POST request to change current login user password
|
||||
Payload
|
||||
{ "current_password":"Demo@123",
|
||||
"new_password":"Demo@123"
|
||||
}
|
||||
"""
|
||||
serializer = ChangePasswordSerializer(
|
||||
context=request.user,
|
||||
@ -219,7 +286,12 @@ class ChangePasswordAPIView(views.APIView):
|
||||
)
|
||||
|
||||
class ResetPasswordAPIView(views.APIView):
|
||||
"""Reset password"""
|
||||
"""Reset password
|
||||
Payload
|
||||
{
|
||||
"verification_code":"373770",
|
||||
"password":"Demo@1323"
|
||||
}"""
|
||||
def post(self, request):
|
||||
serializer = ResetPasswordSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
@ -234,8 +306,12 @@ class ForgotPasswordAPIView(views.APIView):
|
||||
serializer_class = ForgotPasswordSerializer
|
||||
|
||||
def post(self, request):
|
||||
|
||||
"""
|
||||
Post method to validate serializer
|
||||
Payload
|
||||
{
|
||||
"email": "abc@yopmail.com"
|
||||
}
|
||||
"""
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
@ -262,7 +338,6 @@ class ForgotPasswordAPIView(views.APIView):
|
||||
response_status=status.HTTP_200_OK
|
||||
)
|
||||
|
||||
|
||||
class SendPhoneOtp(viewsets.ModelViewSet):
|
||||
"""Send otp on phone"""
|
||||
serializer_class = UserPhoneOtpSerializer
|
||||
@ -310,22 +385,24 @@ class UserLogin(viewsets.ViewSet):
|
||||
if user is not None:
|
||||
login(request, user)
|
||||
if str(user_type) == USER_TYPE_FLAG["TWO"]:
|
||||
guardian_data = Guardian.objects.filter(user__username=username, is_verified=True).last()
|
||||
guardian_data = Guardian.objects.filter(user__username=username).last()
|
||||
if guardian_data:
|
||||
serializer = GuardianSerializer(
|
||||
guardian_data, context={'user_type': user_type}
|
||||
).data
|
||||
if guardian_data.is_verified:
|
||||
serializer = GuardianSerializer(
|
||||
guardian_data, context={'user_type': user_type}
|
||||
).data
|
||||
else:
|
||||
return custom_error_response(
|
||||
ERROR_CODE["2070"],
|
||||
response_status=status.HTTP_401_UNAUTHORIZED
|
||||
)
|
||||
elif str(user_type) == USER_TYPE_FLAG["FIRST"]:
|
||||
junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last()
|
||||
junior_data = Junior.objects.filter(auth__username=username).last()
|
||||
if junior_data:
|
||||
serializer = JuniorSerializer(
|
||||
junior_data, context={'user_type': user_type}
|
||||
).data
|
||||
if junior_data.is_verified:
|
||||
serializer = JuniorSerializer(
|
||||
junior_data, context={'user_type': user_type}
|
||||
).data
|
||||
else:
|
||||
return custom_error_response(
|
||||
ERROR_CODE["2071"],
|
||||
@ -418,7 +495,12 @@ class AdminLoginViewSet(viewsets.GenericViewSet):
|
||||
|
||||
|
||||
class UserEmailVerification(viewsets.ModelViewSet):
|
||||
"""User Email verification"""
|
||||
"""User Email verification
|
||||
Payload
|
||||
{
|
||||
"email":"ramu@yopmail.com",
|
||||
"otp":"361123"
|
||||
}"""
|
||||
serializer_class = EmailVerificationSerializer
|
||||
http_method_names = ('post',)
|
||||
|
||||
@ -465,8 +547,11 @@ class ReSendEmailOtp(viewsets.ModelViewSet):
|
||||
"""Send otp on phone"""
|
||||
serializer_class = EmailVerificationSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
http_method_names = ('post',)
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""Param
|
||||
{"email":"ashok@yopmail.com"}
|
||||
"""
|
||||
otp = generate_otp()
|
||||
if User.objects.filter(email=request.data['email']):
|
||||
expiry = timezone.now() + timezone.timedelta(days=1)
|
||||
@ -478,7 +563,7 @@ class ReSendEmailOtp(viewsets.ModelViewSet):
|
||||
email_data.otp = otp
|
||||
email_data.expired_at = expiry
|
||||
email_data.save()
|
||||
send_otp_email(request.data['email'], otp)
|
||||
send_otp_email.delay(request.data['email'], otp)
|
||||
return custom_response(SUCCESS_CODE['3016'], response_status=status.HTTP_200_OK)
|
||||
else:
|
||||
return custom_error_response(ERROR_CODE["2023"], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
@ -487,23 +572,28 @@ class ProfileAPIViewSet(viewsets.ModelViewSet):
|
||||
"""Profile viewset"""
|
||||
serializer_class = JuniorProfileSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('get',)
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""profile view"""
|
||||
if str(self.request.GET.get('user_type')) == '1':
|
||||
"""profile view
|
||||
Params
|
||||
user_type"""
|
||||
user_type = request.META.get('HTTP_USER_TYPE')
|
||||
if str(user_type) == '1':
|
||||
junior_data = Junior.objects.filter(auth=self.request.user).last()
|
||||
if junior_data:
|
||||
serializer = JuniorProfileSerializer(junior_data)
|
||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||
elif str(self.request.GET.get('user_type')) == '2':
|
||||
elif str(user_type) == '2':
|
||||
guardian_data = Guardian.objects.filter(user=self.request.user).last()
|
||||
if guardian_data:
|
||||
serializer = GuardianProfileSerializer(guardian_data)
|
||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||
|
||||
return custom_error_response(None, response_status=status.HTTP_400_BAD_REQUEST)
|
||||
class UploadImageAPIViewSet(viewsets.ModelViewSet):
|
||||
"""upload task image"""
|
||||
serializer_class = DefaultTaskImagesSerializer
|
||||
http_method_names = ('post',)
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""upload images"""
|
||||
image_data = request.data['image_url']
|
||||
@ -523,6 +613,7 @@ class DefaultImageAPIViewSet(viewsets.ModelViewSet):
|
||||
"""Profile viewset"""
|
||||
serializer_class = DefaultTaskImagesDetailsSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('get',)
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""profile view"""
|
||||
queryset = DefaultTaskImages.objects.all()
|
||||
@ -531,7 +622,13 @@ class DefaultImageAPIViewSet(viewsets.ModelViewSet):
|
||||
|
||||
|
||||
class DeleteUserProfileAPIViewSet(viewsets.GenericViewSet):
|
||||
""" Delete user API view set """
|
||||
""" Delete user API view set
|
||||
{"user_type":1,
|
||||
"signup_method":"1",
|
||||
"password":"Demo@123"}
|
||||
signup_method 1 for manual
|
||||
2 for google login
|
||||
3 for apple login"""
|
||||
|
||||
@action(detail=False, methods=['POST'], url_path='user-account',serializer_class=UserDeleteSerializer,
|
||||
permission_classes=[IsAuthenticated])
|
||||
@ -553,8 +650,9 @@ class UserNotificationAPIViewSet(viewsets.ModelViewSet):
|
||||
"""notification viewset"""
|
||||
serializer_class = UserNotificationSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('get',)
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""profile view"""
|
||||
"""notification view"""
|
||||
queryset = UserNotification.objects.filter(user=request.user)
|
||||
serializer = UserNotificationSerializer(queryset, many=True)
|
||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||
@ -564,9 +662,14 @@ class UpdateUserNotificationAPIViewSet(viewsets.ModelViewSet):
|
||||
"""Update notification viewset"""
|
||||
serializer_class = UpdateUserNotificationSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('post',)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""profile view"""
|
||||
"""Payload
|
||||
{"email_notification": false,
|
||||
"sms_notification": false,
|
||||
"push_notification": false}
|
||||
"""
|
||||
serializer = UpdateUserNotificationSerializer(data=request.data,
|
||||
context=request.user)
|
||||
if serializer.is_valid():
|
||||
@ -576,7 +679,12 @@ class UpdateUserNotificationAPIViewSet(viewsets.ModelViewSet):
|
||||
|
||||
|
||||
class SendSupportEmail(views.APIView):
|
||||
"""support email api"""
|
||||
"""support email api
|
||||
payload
|
||||
name
|
||||
email
|
||||
message
|
||||
"""
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
def post(self, request):
|
||||
@ -620,3 +728,27 @@ class AccessTokenAPIView(views.APIView):
|
||||
data = {"auth_token": access_token}
|
||||
return custom_response(None, data, response_status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class ForceUpdateViewSet(GenericViewSet, mixins.CreateModelMixin):
|
||||
"""FAQ view set"""
|
||||
|
||||
serializer_class = ForceUpdateSerializer
|
||||
http_method_names = ['post']
|
||||
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""
|
||||
faq create api method
|
||||
:param request:
|
||||
:param args: version, device type
|
||||
:param kwargs:
|
||||
:return: success message
|
||||
"""
|
||||
if ForceUpdate.objects.all().count() >= 2:
|
||||
return custom_error_response(ERROR_CODE['2080'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
obj_data = [ForceUpdate(**item) for item in request.data]
|
||||
try:
|
||||
ForceUpdate.objects.bulk_create(obj_data)
|
||||
return custom_response(SUCCESS_CODE["3046"], response_status=status.HTTP_200_OK)
|
||||
except Exception as e:
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
@ -27,7 +27,7 @@ NUMBER = {
|
||||
'ninety_nine': 99, 'hundred': 100, 'thirty_six_hundred': 3600
|
||||
}
|
||||
|
||||
|
||||
none = "none"
|
||||
|
||||
# Super Admin string constant for 'role'
|
||||
SUPER_ADMIN = "Super Admin"
|
||||
@ -50,7 +50,10 @@ USER_TYPE = (
|
||||
('2', 'guardian'),
|
||||
('3', 'superuser')
|
||||
)
|
||||
|
||||
DEVICE_TYPE = (
|
||||
('1', 'android'),
|
||||
('2', 'ios')
|
||||
)
|
||||
USER_TYPE_FLAG = {
|
||||
"FIRST" : "1",
|
||||
"TWO" : "2",
|
||||
|
||||
@ -101,7 +101,13 @@ ERROR_CODE = {
|
||||
"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",
|
||||
"2074": "You can not complete this task because you does not exist in the system",
|
||||
"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",
|
||||
"2077": "You can not add guardian",
|
||||
"2078": "This junior is not associate with you",
|
||||
"2079": "Please update your app version for enjoying uninterrupted services",
|
||||
"2080": "Can not add App version"
|
||||
|
||||
}
|
||||
"""Success message code"""
|
||||
SUCCESS_CODE = {
|
||||
@ -167,7 +173,8 @@ SUCCESS_CODE = {
|
||||
# remove guardian code request
|
||||
"3044": "Remove guardian code request successfully",
|
||||
# create faq
|
||||
"3045": "Create FAQ data"
|
||||
"3045": "Create FAQ data",
|
||||
"3046": "Add App version successfully"
|
||||
|
||||
}
|
||||
"""status code error"""
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
"""
|
||||
web_admin tasks file
|
||||
"""
|
||||
import datetime
|
||||
|
||||
# third party imports
|
||||
from celery import shared_task
|
||||
from templated_email import send_templated_mail
|
||||
@ -8,6 +10,12 @@ from templated_email import send_templated_mail
|
||||
# django imports
|
||||
from django.conf import settings
|
||||
|
||||
# local imports
|
||||
from base.constants import PENDING, IN_PROGRESS, JUNIOR
|
||||
from guardian.models import JuniorTask
|
||||
from notifications.constants import PENDING_TASK_EXPIRING, IN_PROGRESS_TASK_EXPIRING
|
||||
from notifications.utils import send_notification
|
||||
|
||||
|
||||
@shared_task
|
||||
def send_email_otp(email, verification_code):
|
||||
@ -27,3 +35,45 @@ def send_email_otp(email, verification_code):
|
||||
}
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
@shared_task
|
||||
def send_mail(recipient_list, template, context: dict = None):
|
||||
"""
|
||||
used to send otp on email
|
||||
:param context:
|
||||
:param recipient_list: e-mail list
|
||||
:param template: email template
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
from_email = settings.EMAIL_FROM_ADDRESS
|
||||
recipient_list = recipient_list
|
||||
send_templated_mail(
|
||||
template_name=template,
|
||||
from_email=from_email,
|
||||
recipient_list=recipient_list,
|
||||
context=context
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
@shared_task()
|
||||
def notify_task_expiry():
|
||||
"""
|
||||
task to send notification for those task which expiring soon
|
||||
:return:
|
||||
"""
|
||||
all_pending_tasks = JuniorTask.objects.filter(
|
||||
task_status__in=[PENDING, IN_PROGRESS],
|
||||
due_date__range=[datetime.datetime.now().date(),
|
||||
(datetime.datetime.now().date() + datetime.timedelta(days=1))])
|
||||
if pending_tasks := all_pending_tasks.filter(task_status=PENDING):
|
||||
for task in pending_tasks:
|
||||
send_notification(PENDING_TASK_EXPIRING, None, None, task.junior.auth.id,
|
||||
{'task_id': task.id})
|
||||
if in_progress_tasks := all_pending_tasks.filter(task_status=IN_PROGRESS):
|
||||
for task in in_progress_tasks:
|
||||
send_notification(IN_PROGRESS_TASK_EXPIRING, task.junior.auth.id, JUNIOR, task.guardian.user.id,
|
||||
{'task_id': task.id})
|
||||
return True
|
||||
|
||||
Binary file not shown.
@ -24,13 +24,13 @@ from account.models import UserProfile, UserEmailOtp, UserNotification
|
||||
from account.utils import generate_code
|
||||
from junior.serializers import JuniorDetailSerializer
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||
from base.constants import NUMBER, JUN, ZOD, GRD, Already_register_user
|
||||
from base.constants import NUMBER, JUN, ZOD, GRD, Already_register_user, GUARDIAN
|
||||
from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship
|
||||
from .utils import real_time, convert_timedelta_into_datetime, update_referral_points
|
||||
# notification's constant
|
||||
from notifications.constants import TASK_POINTS, TASK_REJECTED
|
||||
from notifications.constants import TASK_APPROVED, TASK_REJECTED
|
||||
# send notification function
|
||||
from notifications.utils import send_notification, send_notification_to_junior
|
||||
from notifications.utils import send_notification
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
@ -420,8 +420,8 @@ class ApproveTaskSerializer(serializers.ModelSerializer):
|
||||
# update complete time of task
|
||||
# instance.completed_on = real_time()
|
||||
instance.completed_on = timezone.now().astimezone(pytz.utc)
|
||||
send_notification_to_junior.delay(TASK_POINTS, None, junior_details.auth.id,
|
||||
{'task_id': instance.id})
|
||||
send_notification.delay(TASK_APPROVED, instance.guardian.user.id, GUARDIAN,
|
||||
junior_details.auth.id, {'task_id': instance.id})
|
||||
else:
|
||||
# reject the task
|
||||
instance.task_status = str(NUMBER['three'])
|
||||
@ -429,8 +429,8 @@ class ApproveTaskSerializer(serializers.ModelSerializer):
|
||||
# update reject time of task
|
||||
# instance.rejected_on = real_time()
|
||||
instance.rejected_on = timezone.now().astimezone(pytz.utc)
|
||||
send_notification_to_junior.delay(TASK_REJECTED, None, junior_details.auth.id,
|
||||
{'task_id': instance.id})
|
||||
send_notification.delay(TASK_REJECTED, instance.guardian.user.id, GUARDIAN,
|
||||
junior_details.auth.id, {'task_id': instance.id})
|
||||
instance.save()
|
||||
junior_data.save()
|
||||
return junior_details
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
""" Urls files"""
|
||||
"""Django import"""
|
||||
from django.urls import path, include
|
||||
from .views import (SignupViewset, UpdateGuardianProfile, AllTaskListAPIView, CreateTaskAPIView, TaskListAPIView,
|
||||
from .views import (SignupViewset, UpdateGuardianProfile, CreateTaskAPIView, TaskListAPIView,
|
||||
SearchTaskListAPIView, TopJuniorListAPIView, ApproveJuniorAPIView, ApproveTaskAPIView,
|
||||
GuardianListAPIView)
|
||||
"""Third party import"""
|
||||
@ -25,8 +25,6 @@ router.register('sign-up', SignupViewset, basename='sign-up')
|
||||
router.register('create-guardian-profile', UpdateGuardianProfile, basename='update-guardian-profile')
|
||||
# Create Task API"""
|
||||
router.register('create-task', CreateTaskAPIView, basename='create-task')
|
||||
# All Task list API"""
|
||||
router.register('all-task-list', AllTaskListAPIView, basename='all-task-list')
|
||||
# Task list bases on the status API"""
|
||||
router.register('task-list', TaskListAPIView, basename='task-list')
|
||||
# Leaderboard API"""
|
||||
|
||||
@ -21,7 +21,7 @@ from zod_bank.celery import app
|
||||
# notification's constant
|
||||
from notifications.constants import REFERRAL_POINTS
|
||||
# send notification function
|
||||
from notifications.utils import send_notification, send_notification_to_junior
|
||||
from notifications.utils import send_notification
|
||||
|
||||
|
||||
# Define upload image on
|
||||
@ -117,7 +117,7 @@ def update_referral_points(referral_code, referral_code_used):
|
||||
junior_query.total_points = junior_query.total_points + NUMBER['five']
|
||||
junior_query.referral_points = junior_query.referral_points + NUMBER['five']
|
||||
junior_query.save()
|
||||
send_notification_to_junior.delay(REFERRAL_POINTS, None, junior_queryset.auth.id, {})
|
||||
send_notification.delay(REFERRAL_POINTS, None, None, junior_queryset.auth.id, {})
|
||||
|
||||
|
||||
|
||||
|
||||
@ -32,14 +32,14 @@ from .serializers import (UserSerializer, CreateGuardianSerializer, TaskSerializ
|
||||
GuardianDetailListSerializer)
|
||||
from .models import Guardian, JuniorTask
|
||||
from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship
|
||||
from account.models import UserEmailOtp, UserNotification
|
||||
from account.models import UserEmailOtp, UserNotification, UserDeviceDetails
|
||||
from .tasks import generate_otp
|
||||
from account.utils import custom_response, custom_error_response, OTP_EXPIRY, send_otp_email
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||
from base.constants import NUMBER, GUARDIAN_CODE_STATUS
|
||||
from base.constants import NUMBER, GUARDIAN_CODE_STATUS, GUARDIAN
|
||||
from .utils import upload_image_to_alibaba
|
||||
from notifications.constants import REGISTRATION, TASK_ASSIGNED, LEADERBOARD_RANKING
|
||||
from notifications.utils import send_notification_to_junior
|
||||
from notifications.constants import REGISTRATION, TASK_ASSIGNED, ASSOCIATE_APPROVED, ASSOCIATE_REJECTED
|
||||
from notifications.utils import send_notification
|
||||
|
||||
""" Define APIs """
|
||||
# Define Signup API,
|
||||
@ -57,12 +57,14 @@ class SignupViewset(viewsets.ModelViewSet):
|
||||
"""Signup view set"""
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
http_method_names = ('post',)
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""Create user profile"""
|
||||
device_id = request.META.get('HTTP_DEVICE_ID')
|
||||
if request.data['user_type'] in [str(NUMBER['one']), str(NUMBER['two'])]:
|
||||
serializer = UserSerializer(context=request.data['user_type'], data=request.data)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
user = serializer.save()
|
||||
"""Generate otp"""
|
||||
otp = generate_otp()
|
||||
# expire otp after 1 day
|
||||
@ -71,19 +73,20 @@ class SignupViewset(viewsets.ModelViewSet):
|
||||
UserEmailOtp.objects.create(email=request.data['email'], otp=otp,
|
||||
user_type=str(request.data['user_type']), expired_at=expiry)
|
||||
"""Send email to the register user"""
|
||||
send_otp_email(request.data['email'], otp)
|
||||
send_otp_email.delay(request.data['email'], otp)
|
||||
UserDeviceDetails.objects.create(user=user, device_id=device_id)
|
||||
return custom_response(SUCCESS_CODE['3001'],
|
||||
response_status=status.HTTP_200_OK)
|
||||
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
||||
else:
|
||||
return custom_error_response(ERROR_CODE['2028'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class UpdateGuardianProfile(viewsets.ViewSet):
|
||||
"""
|
||||
Update guardian profile
|
||||
"""
|
||||
|
||||
class UpdateGuardianProfile(viewsets.ModelViewSet):
|
||||
"""Update guardian profile"""
|
||||
serializer_class = CreateGuardianSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('post',)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""Create guardian profile"""
|
||||
@ -126,7 +129,11 @@ class AllTaskListAPIView(viewsets.ModelViewSet):
|
||||
|
||||
|
||||
class TaskListAPIView(viewsets.ModelViewSet):
|
||||
"""Update guardian profile"""
|
||||
"""Task list
|
||||
Params
|
||||
status
|
||||
search
|
||||
page"""
|
||||
serializer_class = TaskDetailsSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = (SearchFilter,)
|
||||
@ -163,9 +170,16 @@ class CreateTaskAPIView(viewsets.ModelViewSet):
|
||||
http_method_names = ('post', )
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""
|
||||
image should be in form data
|
||||
"""
|
||||
try:
|
||||
image = request.data['default_image']
|
||||
junior = request.data['junior']
|
||||
junior_id = Junior.objects.filter(id=junior).last()
|
||||
guardian_data = Guardian.objects.filter(user=request.user).last()
|
||||
if guardian_data.guardian_code not in junior_id.guardian_code:
|
||||
return custom_error_response(ERROR_CODE['2078'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
allowed_extensions = ['.jpg', '.jpeg', '.png']
|
||||
if not any(extension in str(image) for extension in allowed_extensions):
|
||||
return custom_error_response(ERROR_CODE['2048'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
@ -187,19 +201,20 @@ class CreateTaskAPIView(viewsets.ModelViewSet):
|
||||
if serializer.is_valid():
|
||||
# save serializer
|
||||
task = serializer.save()
|
||||
junior_id = Junior.objects.filter(id=junior).last()
|
||||
send_notification_to_junior.delay(TASK_ASSIGNED, request.auth.payload['user_id'],
|
||||
junior_id.auth.id, {'task_id': task.id})
|
||||
|
||||
send_notification.delay(TASK_ASSIGNED, request.auth.payload['user_id'], GUARDIAN,
|
||||
junior_id.auth.id, {'task_id': task.id})
|
||||
return custom_response(SUCCESS_CODE['3018'], serializer.data, response_status=status.HTTP_200_OK)
|
||||
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
||||
except Exception as e:
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class SearchTaskListAPIView(viewsets.ModelViewSet):
|
||||
"""Update guardian profile"""
|
||||
"""Filter task"""
|
||||
serializer_class = TaskDetailsSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
pagination_class = PageNumberPagination
|
||||
http_method_names = ('get',)
|
||||
|
||||
def get_queryset(self):
|
||||
"""Get the queryset for the view"""
|
||||
@ -210,7 +225,7 @@ class SearchTaskListAPIView(viewsets.ModelViewSet):
|
||||
return junior_queryset
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""Create guardian profile"""
|
||||
"""Filter task"""
|
||||
try:
|
||||
queryset = self.get_queryset()
|
||||
paginator = self.pagination_class()
|
||||
@ -224,10 +239,12 @@ class SearchTaskListAPIView(viewsets.ModelViewSet):
|
||||
|
||||
|
||||
class TopJuniorListAPIView(viewsets.ModelViewSet):
|
||||
"""Top juniors list"""
|
||||
"""Top juniors list
|
||||
No Params"""
|
||||
queryset = JuniorPoints.objects.all()
|
||||
serializer_class = TopJuniorSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('get',)
|
||||
|
||||
def get_serializer_context(self):
|
||||
# context list
|
||||
@ -242,7 +259,6 @@ class TopJuniorListAPIView(viewsets.ModelViewSet):
|
||||
# Update the position field for each JuniorPoints object
|
||||
for index, junior in enumerate(junior_total_points):
|
||||
junior.position = index + 1
|
||||
send_notification_to_junior.delay(LEADERBOARD_RANKING, None, junior.junior.auth.id, {})
|
||||
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)
|
||||
@ -250,14 +266,17 @@ class TopJuniorListAPIView(viewsets.ModelViewSet):
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
class ApproveJuniorAPIView(viewsets.ViewSet):
|
||||
class ApproveJuniorAPIView(viewsets.ModelViewSet):
|
||||
"""approve junior by guardian"""
|
||||
serializer_class = ApproveJuniorSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
http_method_names = ('post',)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
""" junior list"""
|
||||
""" Use below param
|
||||
{"junior_id":"75",
|
||||
"action":"1"}
|
||||
"""
|
||||
try:
|
||||
guardian = Guardian.objects.filter(user__email=self.request.user).last()
|
||||
# fetch junior query
|
||||
@ -273,23 +292,32 @@ class ApproveJuniorAPIView(viewsets.ViewSet):
|
||||
if serializer.is_valid():
|
||||
# save serializer
|
||||
serializer.save()
|
||||
send_notification.delay(ASSOCIATE_APPROVED, guardian.user.id, GUARDIAN,
|
||||
junior_queryset.auth.id)
|
||||
return custom_response(SUCCESS_CODE['3023'], serializer.data, response_status=status.HTTP_200_OK)
|
||||
else:
|
||||
junior_queryset.guardian_code = None
|
||||
junior_queryset.guardian_code_status = str(NUMBER['one'])
|
||||
junior_queryset.save()
|
||||
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)
|
||||
except Exception as e:
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
class ApproveTaskAPIView(viewsets.ViewSet):
|
||||
class ApproveTaskAPIView(viewsets.ModelViewSet):
|
||||
"""approve junior by guardian"""
|
||||
serializer_class = ApproveTaskSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
http_method_names = ('post',)
|
||||
def create(self, request, *args, **kwargs):
|
||||
""" junior list"""
|
||||
""" Params
|
||||
{"junior_id":"82",
|
||||
"task_id":"43",
|
||||
"action":"1"}
|
||||
action 1 for approve
|
||||
2 for reject
|
||||
"""
|
||||
# action 1 is use for approve and 2 for reject
|
||||
try:
|
||||
guardian = Guardian.objects.filter(user__email=self.request.user).last()
|
||||
@ -317,7 +345,7 @@ class ApproveTaskAPIView(viewsets.ViewSet):
|
||||
serializer.save()
|
||||
return custom_response(SUCCESS_CODE['3026'], response_status=status.HTTP_200_OK)
|
||||
else:
|
||||
return custom_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:
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
@ -329,7 +357,8 @@ class GuardianListAPIView(viewsets.ModelViewSet):
|
||||
http_method_names = ('get',)
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
""" junior list"""
|
||||
""" Guardian list of assosicated junior
|
||||
No Params"""
|
||||
try:
|
||||
guardian_data = JuniorGuardianRelationship.objects.filter(junior__auth__email=self.request.user)
|
||||
# fetch junior object
|
||||
|
||||
@ -16,15 +16,15 @@ from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship, Juni
|
||||
from guardian.tasks import generate_otp
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||
from base.constants import (PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER, JUN, ZOD, EXPIRED,
|
||||
GUARDIAN_CODE_STATUS)
|
||||
GUARDIAN_CODE_STATUS, JUNIOR)
|
||||
from guardian.models import Guardian, JuniorTask
|
||||
from account.models import UserEmailOtp, UserNotification
|
||||
from junior.utils import junior_notification_email, junior_approval_mail
|
||||
from guardian.utils import real_time, update_referral_points, convert_timedelta_into_datetime
|
||||
from notifications.utils import send_notification, send_notification_to_junior, send_notification_to_guardian
|
||||
from notifications.constants import (INVITED_GUARDIAN, APPROVED_JUNIOR, SKIPPED_PROFILE_SETUP, TASK_ACTION,
|
||||
TASK_SUBMITTED)
|
||||
|
||||
from notifications.utils import send_notification
|
||||
from notifications.constants import (ASSOCIATE_REQUEST, JUNIOR_ADDED, TASK_ACTION,
|
||||
)
|
||||
from web_admin.models import ArticleCard
|
||||
|
||||
class ListCharField(serializers.ListField):
|
||||
"""Serializer for Array field"""
|
||||
@ -97,8 +97,9 @@ class CreateJuniorSerializer(serializers.ModelSerializer):
|
||||
if guardian_data:
|
||||
JuniorGuardianRelationship.objects.get_or_create(guardian=guardian_data, junior=junior)
|
||||
junior.guardian_code_status = str(NUMBER['three'])
|
||||
junior_approval_mail(user.email, user.first_name)
|
||||
send_notification_to_guardian.delay(APPROVED_JUNIOR, junior.auth.id, guardian_data.user.id, {})
|
||||
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.passcode = validated_data.get('passcode', junior.passcode)
|
||||
junior.country_name = validated_data.get('country_name', junior.country_name)
|
||||
@ -292,7 +293,7 @@ class AddJuniorSerializer(serializers.ModelSerializer):
|
||||
referral_code_used=guardian_data.referral_code,
|
||||
is_password_set=False, is_verified=True,
|
||||
guardian_code_status=GUARDIAN_CODE_STATUS[1][0])
|
||||
JuniorGuardianRelationship.objects.create(guardian=guardian_data, junior=junior_data,
|
||||
JuniorGuardianRelationship.objects.get_or_create(guardian=guardian_data, junior=junior_data,
|
||||
relationship=relationship)
|
||||
total_junior = Junior.objects.all().count()
|
||||
JuniorPoints.objects.create(junior=junior_data, position=total_junior)
|
||||
@ -304,9 +305,9 @@ class AddJuniorSerializer(serializers.ModelSerializer):
|
||||
# add push notification
|
||||
UserNotification.objects.get_or_create(user=user_data)
|
||||
"""Notification email"""
|
||||
junior_notification_email(email, full_name, email, password)
|
||||
junior_notification_email.delay(email, full_name, email, password)
|
||||
# push notification
|
||||
send_notification_to_junior.delay(SKIPPED_PROFILE_SETUP, None, junior_data.auth.id, {})
|
||||
send_notification.delay(JUNIOR_ADDED, None, None, junior_data.auth.id, {})
|
||||
return junior_data
|
||||
|
||||
|
||||
@ -338,10 +339,8 @@ class CompleteTaskSerializer(serializers.ModelSerializer):
|
||||
instance.task_status = str(NUMBER['four'])
|
||||
instance.is_approved = False
|
||||
instance.save()
|
||||
send_notification_to_junior.delay(TASK_SUBMITTED, instance.guardian.user.id,
|
||||
instance.junior.auth.id, {'task_id': instance.id})
|
||||
send_notification_to_guardian.delay(TASK_ACTION, instance.junior.auth.id,
|
||||
instance.guardian.user.id, {'task_id': instance.id})
|
||||
send_notification.delay(TASK_ACTION, instance.junior.auth.id, JUNIOR,
|
||||
instance.guardian.user.id, {'task_id': instance.id})
|
||||
return instance
|
||||
|
||||
class JuniorPointsSerializer(serializers.ModelSerializer):
|
||||
@ -445,14 +444,13 @@ class AddGuardianSerializer(serializers.ModelSerializer):
|
||||
user_type=str(NUMBER['two']), expired_at=expiry_time,
|
||||
is_verified=True)
|
||||
UserNotification.objects.get_or_create(user=user)
|
||||
JuniorGuardianRelationship.objects.create(guardian=guardian_data, junior=junior_data,
|
||||
JuniorGuardianRelationship.objects.get_or_create(guardian=guardian_data, junior=junior_data,
|
||||
relationship=relationship)
|
||||
|
||||
"""Notification email"""
|
||||
junior_notification_email(email, full_name, email, password)
|
||||
junior_approval_mail(email, full_name)
|
||||
send_notification_to_junior.delay(INVITED_GUARDIAN, guardian_data.user.id, junior_data.auth.id, {})
|
||||
send_notification_to_guardian.delay(APPROVED_JUNIOR, junior_data.auth.id, guardian_data.user.id, {})
|
||||
junior_approval_mail.delay(email, full_name)
|
||||
send_notification.delay(ASSOCIATE_REQUEST, junior_data.auth.id, JUNIOR, guardian_data.user.id, {})
|
||||
return guardian_data
|
||||
|
||||
class StartTaskSerializer(serializers.ModelSerializer):
|
||||
@ -518,3 +516,11 @@ class FAQSerializer(serializers.ModelSerializer):
|
||||
model = FAQ
|
||||
fields = ('id', 'question', 'description')
|
||||
|
||||
class CreateArticleCardSerializer(serializers.ModelSerializer):
|
||||
# Article card Serializer
|
||||
|
||||
class Meta(object):
|
||||
# meta info
|
||||
model = ArticleCard
|
||||
fields = ('id', 'article')
|
||||
|
||||
|
||||
@ -14,6 +14,8 @@ from django.db.models import F
|
||||
# being part of the zod bank and access the platform
|
||||
# define junior notification email
|
||||
# junior approval email
|
||||
from celery import shared_task
|
||||
@shared_task()
|
||||
def junior_notification_email(recipient_email, full_name, email, password):
|
||||
"""Notification email"""
|
||||
from_email = settings.EMAIL_FROM_ADDRESS
|
||||
@ -32,7 +34,7 @@ def junior_notification_email(recipient_email, full_name, email, password):
|
||||
}
|
||||
)
|
||||
return full_name
|
||||
|
||||
@shared_task()
|
||||
def junior_approval_mail(guardian, full_name):
|
||||
"""junior approval mail"""
|
||||
from_email = settings.EMAIL_FROM_ADDRESS
|
||||
|
||||
163
junior/views.py
163
junior/views.py
@ -13,7 +13,9 @@ import requests
|
||||
|
||||
from rest_framework.viewsets import GenericViewSet, mixins
|
||||
"""Django app import"""
|
||||
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
from drf_yasg import openapi
|
||||
from drf_yasg.views import get_schema_view
|
||||
# Import guardian's model,
|
||||
# Import junior's model,
|
||||
# Import account's model,
|
||||
@ -36,15 +38,15 @@ from junior.models import (Junior, JuniorPoints, JuniorGuardianRelationship, Jun
|
||||
from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer,
|
||||
RemoveJuniorSerializer, CompleteTaskSerializer, JuniorPointsSerializer,
|
||||
AddGuardianSerializer, StartTaskSerializer, ReAssignTaskSerializer,
|
||||
RemoveGuardianCodeSerializer, FAQSerializer)
|
||||
RemoveGuardianCodeSerializer, FAQSerializer, CreateArticleCardSerializer)
|
||||
from guardian.models import Guardian, JuniorTask
|
||||
from guardian.serializers import TaskDetailsSerializer, TaskDetailsjuniorSerializer
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||
from base.constants import NUMBER, ARTICLE_STATUS
|
||||
from base.constants import NUMBER, ARTICLE_STATUS, none
|
||||
from account.utils import custom_response, custom_error_response
|
||||
from guardian.utils import upload_image_to_alibaba
|
||||
from .utils import update_positions_based_on_points
|
||||
from notifications.utils import send_notification, send_notification_to_junior
|
||||
from notifications.utils import send_notification
|
||||
from notifications.constants import REMOVE_JUNIOR
|
||||
from web_admin.models import Article, ArticleSurvey, SurveyOption, ArticleCard
|
||||
from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleListSerializer,
|
||||
@ -65,13 +67,14 @@ from web_admin.serializers.article_serializer import (ArticleSerializer, Article
|
||||
# Start task
|
||||
# by junior API
|
||||
# Create your views here.
|
||||
class UpdateJuniorProfile(viewsets.ViewSet):
|
||||
class UpdateJuniorProfile(viewsets.ModelViewSet):
|
||||
"""Update junior profile"""
|
||||
serializer_class = CreateJuniorSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('post',)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""Use CreateJuniorSerializer"""
|
||||
"""Create Junior Profile"""
|
||||
try:
|
||||
request_data = request.data
|
||||
image = request.data.get('image')
|
||||
@ -98,12 +101,16 @@ class UpdateJuniorProfile(viewsets.ViewSet):
|
||||
except Exception as e:
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class ValidateGuardianCode(viewsets.ViewSet):
|
||||
class ValidateGuardianCode(viewsets.ModelViewSet):
|
||||
"""Check guardian code exist or not"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('get',)
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""check guardian code"""
|
||||
"""check guardian code
|
||||
Params
|
||||
"guardian_code"
|
||||
"""
|
||||
try:
|
||||
guardian_code = self.request.GET.get('guardian_code').split(',')
|
||||
for code in guardian_code:
|
||||
@ -155,7 +162,14 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
|
||||
http_method_names = ('post',)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
""" junior list"""
|
||||
""" add junior
|
||||
{ "gender":"1",
|
||||
"first_name":"abc",
|
||||
"last_name":"xyz",
|
||||
"dob":"2023-12-12",
|
||||
"relationship":"2",
|
||||
"email":"abc@yopmail.com"
|
||||
}"""
|
||||
try:
|
||||
info_data = {'user': request.user, 'relationship': str(request.data['relationship']),
|
||||
'email': request.data['email'], 'first_name': request.data['first_name'],
|
||||
@ -171,7 +185,11 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
|
||||
image_url = upload_image_to_alibaba(profile_image, filename)
|
||||
info_data.update({"image": image_url})
|
||||
if user := User.objects.filter(username=request.data['email']).first():
|
||||
self.associate_guardian(user)
|
||||
data = self.associate_guardian(user)
|
||||
if data == none:
|
||||
return custom_error_response(ERROR_CODE['2077'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
elif not data:
|
||||
return custom_error_response(ERROR_CODE['2076'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
return custom_response(SUCCESS_CODE['3021'], response_status=status.HTTP_200_OK)
|
||||
# use AddJuniorSerializer serializer
|
||||
serializer = AddJuniorSerializer(data=request.data, context=info_data)
|
||||
@ -184,9 +202,16 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def associate_guardian(self, user):
|
||||
junior = Junior.objects.filter(auth=user).first()
|
||||
junior = Junior.objects.filter(auth__email=self.request.data['email']).first()
|
||||
guardian = Guardian.objects.filter(user=self.request.user).first()
|
||||
junior.guardian_code = [guardian.guardian_code]
|
||||
if not junior:
|
||||
return none
|
||||
if junior.guardian_code and (guardian.guardian_code in junior.guardian_code):
|
||||
return False
|
||||
if type(junior.guardian_code) is list:
|
||||
junior.guardian_code.append(guardian.guardian_code)
|
||||
else:
|
||||
junior.guardian_code = [guardian.guardian_code]
|
||||
junior.guardian_code_status = str(NUMBER['two'])
|
||||
junior.save()
|
||||
JuniorGuardianRelationship.objects.get_or_create(guardian=guardian, junior=junior,
|
||||
@ -195,7 +220,7 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
|
||||
|
||||
|
||||
class InvitedJuniorAPIView(viewsets.ModelViewSet):
|
||||
"""Junior list of assosicated guardian"""
|
||||
"""Invited Junior list of assosicated guardian"""
|
||||
|
||||
serializer_class = JuniorDetailListSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
@ -209,7 +234,8 @@ class InvitedJuniorAPIView(viewsets.ModelViewSet):
|
||||
is_invited=True)
|
||||
return junior_queryset
|
||||
def list(self, request, *args, **kwargs):
|
||||
""" junior list"""
|
||||
""" Invited Junior list of assosicated guardian
|
||||
No Params"""
|
||||
try:
|
||||
queryset = self.get_queryset()
|
||||
paginator = self.pagination_class()
|
||||
@ -223,12 +249,25 @@ class InvitedJuniorAPIView(viewsets.ModelViewSet):
|
||||
|
||||
|
||||
class FilterJuniorAPIView(viewsets.ModelViewSet):
|
||||
"""Update guardian profile"""
|
||||
"""filter junior profile"""
|
||||
serializer_class = JuniorDetailListSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
pagination_class = PageNumberPagination
|
||||
http_method_names = ('get',)
|
||||
|
||||
@swagger_auto_schema(
|
||||
manual_parameters=[
|
||||
# Example of a query parameter
|
||||
openapi.Parameter(
|
||||
'title', # Query parameter name
|
||||
openapi.IN_QUERY, # Parameter location
|
||||
description='title of the name',
|
||||
type=openapi.TYPE_STRING, # Parameter type
|
||||
),
|
||||
# Add more parameters as needed
|
||||
]
|
||||
)
|
||||
|
||||
def get_queryset(self):
|
||||
"""Get the queryset for the view"""
|
||||
title = self.request.GET.get('title')
|
||||
@ -239,7 +278,7 @@ class FilterJuniorAPIView(viewsets.ModelViewSet):
|
||||
return queryset
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""Create guardian profile"""
|
||||
"""Filter junior"""
|
||||
try:
|
||||
queryset = self.get_queryset()
|
||||
paginator = self.pagination_class()
|
||||
@ -253,7 +292,9 @@ class FilterJuniorAPIView(viewsets.ModelViewSet):
|
||||
|
||||
|
||||
class RemoveJuniorAPIView(views.APIView):
|
||||
"""Remove junior API"""
|
||||
"""Remove junior API
|
||||
Params
|
||||
id=37"""
|
||||
serializer_class = RemoveJuniorSerializer
|
||||
model = Junior
|
||||
permission_classes = [IsAuthenticated]
|
||||
@ -271,7 +312,7 @@ class RemoveJuniorAPIView(views.APIView):
|
||||
if serializer.is_valid():
|
||||
# save serializer
|
||||
serializer.save()
|
||||
send_notification_to_junior.delay(REMOVE_JUNIOR, 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_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
||||
else:
|
||||
@ -281,14 +322,17 @@ class RemoveJuniorAPIView(views.APIView):
|
||||
|
||||
|
||||
class JuniorTaskListAPIView(viewsets.ModelViewSet):
|
||||
"""Update guardian profile"""
|
||||
"""Junior task list"""
|
||||
serializer_class = TaskDetailsjuniorSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
pagination_class = PageNumberPagination
|
||||
http_method_names = ('get',)
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""Create guardian profile"""
|
||||
"""Junior task list
|
||||
status=0
|
||||
search='title'
|
||||
page=1"""
|
||||
try:
|
||||
status_value = self.request.GET.get('status')
|
||||
search = self.request.GET.get('search')
|
||||
@ -318,7 +362,9 @@ class JuniorTaskListAPIView(viewsets.ModelViewSet):
|
||||
|
||||
|
||||
class CompleteJuniorTaskAPIView(views.APIView):
|
||||
"""Update junior task API"""
|
||||
"""Payload
|
||||
task_id
|
||||
image"""
|
||||
serializer_class = CompleteTaskSerializer
|
||||
model = JuniorTask
|
||||
permission_classes = [IsAuthenticated]
|
||||
@ -363,7 +409,8 @@ class JuniorPointsListAPIView(viewsets.ModelViewSet):
|
||||
http_method_names = ('get',)
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""profile view"""
|
||||
"""Junior Points
|
||||
No Params"""
|
||||
try:
|
||||
update_positions_based_on_points()
|
||||
queryset = JuniorPoints.objects.filter(junior__auth__email=self.request.user).last()
|
||||
@ -374,7 +421,7 @@ class JuniorPointsListAPIView(viewsets.ModelViewSet):
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
class ValidateReferralCode(viewsets.ViewSet):
|
||||
class ValidateReferralCode(viewsets.ModelViewSet):
|
||||
"""Check guardian code exist or not"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('get',)
|
||||
@ -409,7 +456,13 @@ class InviteGuardianAPIView(viewsets.ModelViewSet):
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('post',)
|
||||
def create(self, request, *args, **kwargs):
|
||||
""" junior list"""
|
||||
""" add guardian
|
||||
{
|
||||
"first_name":"abc",
|
||||
"last_name":"xyz",
|
||||
"email":"abc@yopmail.com",
|
||||
"relationship":2
|
||||
}"""
|
||||
try:
|
||||
if request.data['email'] == '':
|
||||
return custom_error_response(ERROR_CODE['2062'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
@ -427,7 +480,11 @@ class InviteGuardianAPIView(viewsets.ModelViewSet):
|
||||
|
||||
|
||||
class StartTaskAPIView(views.APIView):
|
||||
"""Update junior task API"""
|
||||
"""Update junior task API
|
||||
Paylod
|
||||
{
|
||||
"task_id":28
|
||||
}"""
|
||||
serializer_class = StartTaskSerializer
|
||||
model = JuniorTask
|
||||
permission_classes = [IsAuthenticated]
|
||||
@ -451,7 +508,13 @@ class StartTaskAPIView(views.APIView):
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class ReAssignJuniorTaskAPIView(views.APIView):
|
||||
"""Update junior task API"""
|
||||
"""Update junior task API
|
||||
Payload
|
||||
{
|
||||
"task_id":34,
|
||||
"due_date":"2023-08-22"
|
||||
}
|
||||
"""
|
||||
serializer_class = ReAssignTaskSerializer
|
||||
model = JuniorTask
|
||||
permission_classes = [IsAuthenticated]
|
||||
@ -480,7 +543,10 @@ class StartArticleAPIView(viewsets.ModelViewSet):
|
||||
http_method_names = ('post',)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
""" junior list"""
|
||||
""" Payload
|
||||
{
|
||||
"article_id":"2"
|
||||
}"""
|
||||
try:
|
||||
junior_instance = Junior.objects.filter(auth=self.request.user).last()
|
||||
article_id = request.data.get('article_id')
|
||||
@ -502,7 +568,7 @@ class StartArticleAPIView(viewsets.ModelViewSet):
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class StartAssessmentAPIView(viewsets.ModelViewSet):
|
||||
"""Junior Points viewset"""
|
||||
"""Question answer viewset"""
|
||||
serializer_class = StartAssessmentSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('get',)
|
||||
@ -515,7 +581,9 @@ class StartAssessmentAPIView(viewsets.ModelViewSet):
|
||||
).order_by('-created_at')
|
||||
return article
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""profile view"""
|
||||
"""Params
|
||||
article_id
|
||||
"""
|
||||
|
||||
try:
|
||||
queryset = self.get_queryset()
|
||||
@ -527,7 +595,9 @@ class StartAssessmentAPIView(viewsets.ModelViewSet):
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class CheckAnswerAPIView(viewsets.ModelViewSet):
|
||||
"""Junior Points viewset"""
|
||||
"""Params
|
||||
question_id=1
|
||||
answer_id=1"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('get',)
|
||||
|
||||
@ -536,7 +606,10 @@ class CheckAnswerAPIView(viewsets.ModelViewSet):
|
||||
article = ArticleSurvey.objects.filter(id=question_id).last()
|
||||
return article
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""profile view"""
|
||||
""" Params
|
||||
question_id=1
|
||||
answer_id=1
|
||||
"""
|
||||
|
||||
try:
|
||||
answer_id = self.request.GET.get('answer_id')
|
||||
@ -560,7 +633,9 @@ class CheckAnswerAPIView(viewsets.ModelViewSet):
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class CompleteArticleAPIView(views.APIView):
|
||||
"""Remove junior API"""
|
||||
"""Params
|
||||
article_id
|
||||
"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('put', 'get',)
|
||||
def put(self, request, format=None):
|
||||
@ -574,7 +649,8 @@ class CompleteArticleAPIView(views.APIView):
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
""" junior list"""
|
||||
""" Params
|
||||
article_id=1"""
|
||||
try:
|
||||
article_id = self.request.GET.get('article_id')
|
||||
total_earn_points = JuniorArticlePoints.objects.filter(junior__auth=request.user,
|
||||
@ -588,12 +664,16 @@ class CompleteArticleAPIView(views.APIView):
|
||||
|
||||
|
||||
class ReadArticleCardAPIView(views.APIView):
|
||||
"""Remove junior API"""
|
||||
"""Read article card API"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('put',)
|
||||
|
||||
def put(self, request, *args, **kwargs):
|
||||
""" junior list"""
|
||||
""" Read article card
|
||||
Payload
|
||||
{"article_id":"1",
|
||||
"article_card":"2",
|
||||
"current_page":"2"}"""
|
||||
try:
|
||||
junior_instance = Junior.objects.filter(auth=self.request.user).last()
|
||||
article = self.request.data.get('article_id')
|
||||
@ -611,11 +691,14 @@ class ReadArticleCardAPIView(views.APIView):
|
||||
|
||||
class CreateArticleCardAPIView(viewsets.ModelViewSet):
|
||||
"""Start article"""
|
||||
serializer_class = CreateArticleCardSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('post',)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
""" junior list"""
|
||||
""" create article card
|
||||
Params
|
||||
{"article_id":1}"""
|
||||
try:
|
||||
junior_instance = Junior.objects.filter(auth=self.request.user).last()
|
||||
article_id = request.data.get('article_id')
|
||||
@ -634,7 +717,8 @@ class CreateArticleCardAPIView(viewsets.ModelViewSet):
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class RemoveGuardianCodeAPIView(views.APIView):
|
||||
"""Update junior task API"""
|
||||
"""Remove guardian code request API
|
||||
No Payload"""
|
||||
serializer_class = RemoveGuardianCodeSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@ -671,7 +755,7 @@ class FAQViewSet(GenericViewSet, mixins.CreateModelMixin,
|
||||
"""
|
||||
faq create api method
|
||||
:param request:
|
||||
:param args:
|
||||
:param args: question, description
|
||||
:param kwargs:
|
||||
:return: success message
|
||||
"""
|
||||
@ -697,6 +781,3 @@ class FAQViewSet(GenericViewSet, mixins.CreateModelMixin,
|
||||
serializer = self.serializer_class(paginated_queryset, many=True)
|
||||
return custom_response(None, data=serializer.data, response_status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -10,3 +10,4 @@ from notifications.models import Notification
|
||||
class NotificationAdmin(admin.ModelAdmin):
|
||||
"""Notification Admin"""
|
||||
list_display = ['id', 'notification_type', 'notification_to', 'data', 'is_read']
|
||||
list_filter = ['notification_type']
|
||||
|
||||
@ -1,19 +1,21 @@
|
||||
"""
|
||||
notification constants file
|
||||
"""
|
||||
from base.constants import NUMBER
|
||||
REGISTRATION = NUMBER['one']
|
||||
TASK_ASSIGNED = NUMBER['two']
|
||||
INVITED_GUARDIAN = NUMBER['three']
|
||||
APPROVED_JUNIOR = NUMBER['four']
|
||||
REFERRAL_POINTS = NUMBER['five']
|
||||
TASK_POINTS = NUMBER['six']
|
||||
TASK_REJECTED = NUMBER['seven']
|
||||
SKIPPED_PROFILE_SETUP = NUMBER['eight']
|
||||
TASK_SUBMITTED = NUMBER['nine']
|
||||
TASK_ACTION = NUMBER['ten']
|
||||
LEADERBOARD_RANKING = NUMBER['eleven']
|
||||
REMOVE_JUNIOR = NUMBER['twelve']
|
||||
REGISTRATION = 1
|
||||
ASSOCIATE_REQUEST = 3
|
||||
ASSOCIATE_REJECTED = 4
|
||||
ASSOCIATE_APPROVED = 5
|
||||
REFERRAL_POINTS = 6
|
||||
JUNIOR_ADDED = 7
|
||||
|
||||
TASK_ASSIGNED = 8
|
||||
TASK_ACTION = 9
|
||||
TASK_REJECTED = 10
|
||||
TASK_APPROVED = 11
|
||||
PENDING_TASK_EXPIRING = 12
|
||||
IN_PROGRESS_TASK_EXPIRING = 13
|
||||
REMOVE_JUNIOR = 15
|
||||
|
||||
TEST_NOTIFICATION = 99
|
||||
|
||||
NOTIFICATION_DICT = {
|
||||
@ -21,50 +23,72 @@ NOTIFICATION_DICT = {
|
||||
"title": "Successfully registered!",
|
||||
"body": "You have registered successfully. Now login and complete your profile."
|
||||
},
|
||||
TASK_ASSIGNED: {
|
||||
"title": "New task assigned !!",
|
||||
"body": "{from_user} has assigned you a new task."
|
||||
},
|
||||
INVITED_GUARDIAN: {
|
||||
"title": "Invite guardian",
|
||||
"body": "Invite guardian successfully"
|
||||
},
|
||||
APPROVED_JUNIOR: {
|
||||
"title": "Approve junior !",
|
||||
# user will receive notification as soon junior sign up application using their guardian code
|
||||
# for association
|
||||
ASSOCIATE_REQUEST: {
|
||||
"title": "Associate request!",
|
||||
"body": "You have request from {from_user} to associate with you."
|
||||
},
|
||||
# Juniors will receive notification when custodians reject their request for associate
|
||||
ASSOCIATE_REJECTED: {
|
||||
"title": "Associate request rejected!",
|
||||
"body": "Your request to associate has been rejected by {from_user}."
|
||||
},
|
||||
# Juniors will receive notification when custodians approve their request for associate
|
||||
ASSOCIATE_APPROVED: {
|
||||
"title": "Associate request approved!",
|
||||
"body": "Your request to associate has been approved by {from_user}."
|
||||
},
|
||||
# Juniors will receive Notifications for every Points earned by referrals
|
||||
REFERRAL_POINTS: {
|
||||
"title": "Earn Referral points",
|
||||
"title": "Earn Referral points!",
|
||||
"body": "You earn 5 points for referral."
|
||||
},
|
||||
TASK_POINTS: {
|
||||
"title": "Earn Task points!",
|
||||
"body": "You earn 5 points for task."
|
||||
# Juniors will receive notification once any custodians add them in their account
|
||||
JUNIOR_ADDED: {
|
||||
"title": "Profile already setup!",
|
||||
"body": "Your guardian has already setup your profile."
|
||||
},
|
||||
TASK_REJECTED: {
|
||||
"title": "Task rejected!",
|
||||
"body": "Your task has been rejected."
|
||||
},
|
||||
SKIPPED_PROFILE_SETUP: {
|
||||
"title": "Skipped profile setup!",
|
||||
"body": "Your guardian {from_user} has setup your profile."
|
||||
},
|
||||
TASK_SUBMITTED: {
|
||||
"title": "Task submitted!",
|
||||
"body": "Your task has been submitted successfully."
|
||||
# Juniors will receive Notification for every Task Assign by Custodians
|
||||
TASK_ASSIGNED: {
|
||||
"title": "New task assigned!",
|
||||
"body": "{from_user} has assigned you a new task."
|
||||
},
|
||||
# Guardian will receive notification as soon as junior send task for approval
|
||||
TASK_ACTION: {
|
||||
"title": "Task completion approval!",
|
||||
"body": "You have request from {from_user} for task approval."
|
||||
"body": "{from_user} completed her task {task_name}."
|
||||
},
|
||||
LEADERBOARD_RANKING: {
|
||||
"title": "Leader board rank!",
|
||||
"body": "Your rank is ."
|
||||
# Juniors will receive notification as soon as their task is rejected by custodians
|
||||
TASK_REJECTED: {
|
||||
"title": "Task completion rejected!",
|
||||
"body": "Your task completion request has been rejected by {from_user}."
|
||||
},
|
||||
# Juniors will receive notification as soon as their task is approved by custodians
|
||||
# and for every Points earned by Task completion
|
||||
TASK_APPROVED: {
|
||||
"title": "Task completion approved!",
|
||||
"body": "Your task completion request has been approved by {from_user}. "
|
||||
"Also you earned 5 points for successful completion."
|
||||
},
|
||||
# Juniors will receive notification when their task end date about to end
|
||||
PENDING_TASK_EXPIRING: {
|
||||
"title": "Task expiring soon!",
|
||||
"body": "Your task {task_name} is expiring soon. Please complete it."
|
||||
},
|
||||
# User will receive notification when their assigned task is about to end
|
||||
# and juniors have not performed any action
|
||||
IN_PROGRESS_TASK_EXPIRING: {
|
||||
"title": "Task 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."
|
||||
},
|
||||
# Juniors will receive notification as soon as their custodians remove them from account
|
||||
REMOVE_JUNIOR: {
|
||||
"title": "Disassociate by guardian!",
|
||||
"body": "Your guardian disassociate you ."
|
||||
"body": "Your guardian has disassociated you."
|
||||
},
|
||||
# Test notification
|
||||
TEST_NOTIFICATION: {
|
||||
"title": "Test Notification",
|
||||
"body": "This notification is for testing purpose from {from_user}."
|
||||
|
||||
@ -40,6 +40,8 @@ class NotificationListSerializer(serializers.ModelSerializer):
|
||||
|
||||
class ReadNotificationSerializer(serializers.ModelSerializer):
|
||||
"""User task Serializer"""
|
||||
id = serializers.ListSerializer(child=serializers.IntegerField())
|
||||
|
||||
class Meta(object):
|
||||
"""Meta class"""
|
||||
model = Notification
|
||||
|
||||
@ -6,7 +6,7 @@ from django.urls import path, include
|
||||
from rest_framework import routers
|
||||
|
||||
# local imports
|
||||
from notifications.views import NotificationViewSet, ReadNotification
|
||||
from notifications.views import NotificationViewSet
|
||||
|
||||
# initiate router
|
||||
router = routers.SimpleRouter()
|
||||
@ -15,5 +15,4 @@ router.register('notifications', NotificationViewSet, basename='notifications')
|
||||
|
||||
urlpatterns = [
|
||||
path('api/v1/', include(router.urls)),
|
||||
path('api/v1/read-notification/', ReadNotification.as_view()),
|
||||
]
|
||||
|
||||
@ -9,15 +9,15 @@ from firebase_admin.messaging import Message, Notification as FirebaseNotificati
|
||||
# django imports
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
# local imports
|
||||
from account.models import UserNotification
|
||||
from account.utils import get_user_full_name
|
||||
from guardian.models import Guardian
|
||||
from base.constants import GUARDIAN, JUNIOR
|
||||
from guardian.models import Guardian, JuniorTask
|
||||
from junior.models import Junior
|
||||
from notifications.constants import NOTIFICATION_DICT
|
||||
from notifications.models import Notification
|
||||
|
||||
# local imports
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
@ -42,49 +42,69 @@ def remove_fcm_token(user_id: int, access_token: str, registration_id) -> None:
|
||||
print(e)
|
||||
|
||||
|
||||
def get_basic_detail(from_user_id, to_user_id):
|
||||
def get_from_user_details(from_user_id, from_user_type):
|
||||
"""
|
||||
used to get the basic details
|
||||
used to get from user details
|
||||
"""
|
||||
from_user = User.objects.get(id=from_user_id) if from_user_id else None
|
||||
to_user = User.objects.get(id=to_user_id)
|
||||
return from_user, to_user
|
||||
from_user = None
|
||||
from_user_name = None
|
||||
from_user_image = None
|
||||
if from_user_id:
|
||||
if from_user_type == GUARDIAN:
|
||||
guardian = Guardian.objects.filter(user_id=from_user_id).select_related('user').first()
|
||||
from_user = guardian.user
|
||||
from_user_name = get_user_full_name(from_user)
|
||||
from_user_image = guardian.image
|
||||
elif from_user_type == JUNIOR:
|
||||
junior = Junior.objects.filter(auth_id=from_user_id).select_related('auth').first()
|
||||
from_user = junior.auth
|
||||
from_user_name = get_user_full_name(from_user)
|
||||
from_user_image = junior.image
|
||||
return from_user_name, from_user_image, from_user
|
||||
|
||||
|
||||
def get_notification_data(notification_type, from_user, to_user, extra_data):
|
||||
def get_notification_data(notification_type, from_user_id, from_user_type, to_user_id, extra_data):
|
||||
"""
|
||||
get notification and push data
|
||||
:param from_user_type: GUARDIAN or JUNIOR
|
||||
:param notification_type: notification_type
|
||||
:param from_user: from_user obj
|
||||
:param to_user: to_user obj
|
||||
:param from_user_id: from_user obj
|
||||
:param to_user_id: to_user obj
|
||||
:param extra_data: any extra data provided
|
||||
:return: notification and push data
|
||||
"""
|
||||
push_data = NOTIFICATION_DICT[notification_type].copy()
|
||||
notification_data = push_data.copy()
|
||||
notification_data['to_user'] = get_user_full_name(to_user)
|
||||
if from_user:
|
||||
from_user_name = get_user_full_name(from_user)
|
||||
push_data['body'] = push_data['body'].format(from_user=from_user_name)
|
||||
notification_data['body'] = notification_data['body'].format(from_user=from_user_name)
|
||||
notification_data['from_user'] = from_user_name
|
||||
task_name = None
|
||||
if 'task_id' in extra_data:
|
||||
task = JuniorTask.objects.filter(id=extra_data.get('task_id')).first()
|
||||
task_name = task.task_name
|
||||
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)
|
||||
|
||||
push_data['body'] = push_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)
|
||||
notification_data['from_user'] = from_user_name
|
||||
notification_data['from_user_image'] = from_user_image
|
||||
|
||||
notification_data.update(extra_data)
|
||||
|
||||
return notification_data, push_data
|
||||
to_user = User.objects.get(id=to_user_id)
|
||||
return notification_data, push_data, from_user, to_user
|
||||
|
||||
|
||||
def send_notification(notification_type, from_user, to_user, extra_data):
|
||||
@shared_task()
|
||||
def send_notification(notification_type, from_user_id, from_user_type, to_user_id, extra_data):
|
||||
"""
|
||||
used to send the push for the given notification type
|
||||
"""
|
||||
# (from_user, to_user) = get_basic_detail(from_user_id, to_user_id)
|
||||
notification_data, push_data = get_notification_data(notification_type, from_user, to_user, extra_data)
|
||||
notification_data, push_data, from_user, to_user = get_notification_data(notification_type, from_user_id,
|
||||
from_user_type, to_user_id, extra_data)
|
||||
user_notification_type = UserNotification.objects.filter(user=to_user).first()
|
||||
notification_data.update({'badge': Notification.objects.filter(notification_to=to_user, is_read=False).count()})
|
||||
Notification.objects.create(notification_type=notification_type, notification_from=from_user,
|
||||
notification_to=to_user, data=notification_data)
|
||||
if user_notification_type.push_notification:
|
||||
if user_notification_type and user_notification_type.push_notification:
|
||||
send_push(to_user, push_data)
|
||||
|
||||
|
||||
@ -97,25 +117,31 @@ def send_push(user, data):
|
||||
|
||||
@shared_task()
|
||||
def send_notification_to_guardian(notification_type, from_user_id, to_user_id, extra_data):
|
||||
from_user = None
|
||||
"""
|
||||
:param notification_type:
|
||||
:param from_user_id:
|
||||
:param to_user_id:
|
||||
:param extra_data:
|
||||
:return:
|
||||
"""
|
||||
if from_user_id:
|
||||
from_user = Junior.objects.filter(auth_id=from_user_id).select_related('auth').first()
|
||||
from_user = Junior.objects.filter(auth_id=from_user_id).first()
|
||||
extra_data['from_user_image'] = from_user.image
|
||||
from_user = from_user.auth
|
||||
to_user = Guardian.objects.filter(user_id=to_user_id).select_related('user').first()
|
||||
extra_data['to_user_image'] = to_user.image
|
||||
send_notification(notification_type, from_user, to_user.user, extra_data)
|
||||
send_notification(notification_type, from_user_id, to_user_id, extra_data)
|
||||
|
||||
|
||||
@shared_task()
|
||||
def send_notification_to_junior(notification_type, from_user_id, to_user_id, extra_data):
|
||||
from_user = None
|
||||
"""
|
||||
:param notification_type:
|
||||
:param from_user_id:
|
||||
:param to_user_id:
|
||||
:param extra_data:
|
||||
:return:
|
||||
"""
|
||||
if from_user_id:
|
||||
from_user = Guardian.objects.filter(user_id=from_user_id).select_related('user').first()
|
||||
from_user = Guardian.objects.filter(user_id=from_user_id).first()
|
||||
extra_data['from_user_image'] = from_user.image
|
||||
from_user = from_user.user
|
||||
to_user = Junior.objects.filter(auth_id=to_user_id).select_related('auth').first()
|
||||
extra_data['to_user_image'] = to_user.image
|
||||
send_notification(notification_type, from_user, to_user.auth, extra_data)
|
||||
send_notification(notification_type, from_user_id, to_user_id, extra_data)
|
||||
|
||||
|
||||
|
||||
@ -4,41 +4,40 @@ notifications views file
|
||||
# django imports
|
||||
from django.db.models import Q
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import viewsets, status, views
|
||||
|
||||
# local imports
|
||||
from account.utils import custom_response, custom_error_response
|
||||
from base.messages import SUCCESS_CODE, ERROR_CODE
|
||||
from base.tasks import notify_task_expiry
|
||||
from notifications.constants import TEST_NOTIFICATION
|
||||
# Import serializer
|
||||
from notifications.serializers import RegisterDevice, NotificationListSerializer, ReadNotificationSerializer
|
||||
from notifications.utils import send_notification, send_notification_to_guardian, send_notification_to_junior
|
||||
# Import model
|
||||
from notifications.utils import send_notification
|
||||
from notifications.models import Notification
|
||||
|
||||
|
||||
class NotificationViewSet(viewsets.GenericViewSet):
|
||||
""" used to do the notification actions """
|
||||
"""
|
||||
used to do the notification actions
|
||||
"""
|
||||
serializer_class = NotificationListSerializer
|
||||
permission_classes = [IsAuthenticated, ]
|
||||
|
||||
def list(self, request, *args, **kwargs) -> Response:
|
||||
""" list the notifications """
|
||||
"""
|
||||
to list user's notifications
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
queryset = Notification.objects.filter(notification_to_id=request.auth.payload['user_id']
|
||||
).select_related('notification_to').order_by('-id')
|
||||
paginator = self.pagination_class()
|
||||
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
||||
serializer = self.serializer_class(paginated_queryset, many=True)
|
||||
self.mark_notifications_as_read(serializer.data)
|
||||
return custom_response(None, serializer.data)
|
||||
|
||||
@staticmethod
|
||||
def mark_notifications_as_read(data):
|
||||
""" used to mark notification queryset as read """
|
||||
ids = [obj['id'] for obj in data]
|
||||
Notification.objects.filter(id__in=ids).update(is_read=True)
|
||||
|
||||
@action(methods=['post'], detail=False, url_path='device', url_name='device', serializer_class=RegisterDevice)
|
||||
def fcm_registration(self, request):
|
||||
"""
|
||||
@ -56,38 +55,24 @@ class NotificationViewSet(viewsets.GenericViewSet):
|
||||
to send test notification
|
||||
:return:
|
||||
"""
|
||||
send_notification_to_guardian.delay(TEST_NOTIFICATION, None, request.auth.payload['user_id'],
|
||||
{'task_id': None})
|
||||
send_notification_to_junior.delay(TEST_NOTIFICATION, None, request.auth.payload['user_id'],
|
||||
{'task_id': None})
|
||||
send_notification(TEST_NOTIFICATION, None, None, request.auth.payload['user_id'],
|
||||
{})
|
||||
return custom_response(SUCCESS_CODE["3000"])
|
||||
|
||||
@action(methods=['get'], detail=False, url_path='list', url_name='list',
|
||||
serializer_class=NotificationListSerializer)
|
||||
def notification_list(self, request):
|
||||
@action(methods=['patch'], url_path='mark-as-read', url_name='mark-as-read', detail=False,
|
||||
serializer_class=ReadNotificationSerializer)
|
||||
def mark_as_read(self, request, *args, **kwargs):
|
||||
"""
|
||||
notification list
|
||||
"""
|
||||
try:
|
||||
queryset = Notification.objects.filter(notification_to=request.user)
|
||||
serializer = NotificationListSerializer(queryset, many=True)
|
||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||
except Exception as e:
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
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)
|
||||
|
||||
|
||||
class ReadNotification(views.APIView):
|
||||
"""Update notification API"""
|
||||
serializer_class = ReadNotificationSerializer
|
||||
model = Notification
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def put(self, request, format=None):
|
||||
try:
|
||||
notification_id = self.request.data.get('notification_id')
|
||||
notification_queryset = Notification.objects.filter(id__in=notification_id,
|
||||
notification_to=self.request.user).update(is_read=True)
|
||||
if notification_queryset:
|
||||
return custom_response(SUCCESS_CODE['3039'], response_status=status.HTTP_200_OK)
|
||||
except Exception as e:
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
@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)
|
||||
|
||||
@ -7,6 +7,7 @@ from rest_framework import serializers
|
||||
# django imports
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from account.utils import get_user_full_name
|
||||
# local imports
|
||||
from base.constants import USER_TYPE
|
||||
|
||||
@ -74,6 +75,7 @@ class UserCSVReportSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
user csv/xls report serializer
|
||||
"""
|
||||
name = serializers.SerializerMethodField()
|
||||
phone_number = serializers.SerializerMethodField()
|
||||
user_type = serializers.SerializerMethodField()
|
||||
is_active = serializers.SerializerMethodField()
|
||||
@ -84,7 +86,15 @@ class UserCSVReportSerializer(serializers.ModelSerializer):
|
||||
meta class
|
||||
"""
|
||||
model = USER
|
||||
fields = ('first_name', 'last_name', 'email', 'phone_number', 'user_type', 'is_active', 'date_joined')
|
||||
fields = ('name', 'email', 'phone_number', 'user_type', 'is_active', 'date_joined')
|
||||
|
||||
@staticmethod
|
||||
def get_name(obj):
|
||||
"""
|
||||
:param obj: user object
|
||||
:return: full name
|
||||
"""
|
||||
return get_user_full_name(obj)
|
||||
|
||||
@staticmethod
|
||||
def get_phone_number(obj):
|
||||
|
||||
@ -14,7 +14,7 @@ from account.models import UserEmailOtp
|
||||
from base.constants import USER_TYPE
|
||||
from base.messages import ERROR_CODE
|
||||
from guardian.tasks import generate_otp
|
||||
from base.tasks import send_email_otp
|
||||
from base.tasks import send_mail
|
||||
|
||||
USER = get_user_model()
|
||||
|
||||
@ -48,11 +48,13 @@ class AdminOTPSerializer(serializers.ModelSerializer):
|
||||
:return: user_data
|
||||
"""
|
||||
email = validated_data['email']
|
||||
|
||||
verification_code = generate_otp()
|
||||
|
||||
template = 'email_reset_verification.email'
|
||||
# Send the verification code to the user's email
|
||||
send_email_otp.delay(email, verification_code)
|
||||
data = {
|
||||
"verification_code": verification_code
|
||||
}
|
||||
send_mail.delay([email], template, data)
|
||||
|
||||
expiry = timezone.now() + timezone.timedelta(days=1)
|
||||
user_data, created = UserEmailOtp.objects.update_or_create(email=email,
|
||||
|
||||
@ -5,6 +5,7 @@ web_admin user_management serializers file
|
||||
from rest_framework import serializers
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from account.utils import get_user_full_name
|
||||
from base.constants import USER_TYPE, GUARDIAN, JUNIOR
|
||||
# local imports
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||
@ -37,7 +38,7 @@ class UserManagementListSerializer(serializers.ModelSerializer):
|
||||
:param obj: user object
|
||||
:return: full name
|
||||
"""
|
||||
return f"{obj.first_name} {obj.last_name}" if obj.last_name else obj.first_name
|
||||
return get_user_full_name(obj)
|
||||
|
||||
@staticmethod
|
||||
def get_country_code(obj):
|
||||
@ -144,7 +145,7 @@ class GuardianSerializer(serializers.ModelSerializer):
|
||||
:param obj: guardian object
|
||||
:return: full name
|
||||
"""
|
||||
return f"{obj.user.first_name} {obj.user.last_name}" if obj.user.last_name else obj.user.first_name
|
||||
return get_user_full_name(obj.user)
|
||||
|
||||
@staticmethod
|
||||
def get_first_name(obj):
|
||||
@ -222,7 +223,7 @@ class JuniorSerializer(serializers.ModelSerializer):
|
||||
:param obj: junior object
|
||||
: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
|
||||
def get_first_name(obj):
|
||||
|
||||
@ -2,8 +2,9 @@
|
||||
web_utils file
|
||||
"""
|
||||
import base64
|
||||
import datetime
|
||||
|
||||
from base.constants import ARTICLE_CARD_IMAGE_FOLDER
|
||||
from base.constants import ARTICLE_CARD_IMAGE_FOLDER, DATE_FORMAT
|
||||
from guardian.utils import upload_image_to_alibaba, upload_base64_image_to_alibaba
|
||||
|
||||
|
||||
@ -40,3 +41,21 @@ def get_image_url(data):
|
||||
# upload image on ali baba
|
||||
image_url = upload_image_to_alibaba(image, filename)
|
||||
return image_url
|
||||
|
||||
|
||||
def get_dates(start_date, end_date):
|
||||
"""
|
||||
to get start and end date
|
||||
:param start_date: format (yyyy-mm-dd)
|
||||
:param end_date: format (yyyy-mm-dd)
|
||||
:return: start and end date
|
||||
"""
|
||||
|
||||
if start_date and end_date:
|
||||
start_date = datetime.datetime.strptime(start_date, DATE_FORMAT).date()
|
||||
end_date = datetime.datetime.strptime(end_date, DATE_FORMAT).date()
|
||||
else:
|
||||
end_date = datetime.date.today()
|
||||
start_date = end_date - datetime.timedelta(days=6)
|
||||
|
||||
return start_date, end_date
|
||||
|
||||
@ -6,9 +6,6 @@ import datetime
|
||||
import io
|
||||
import pandas as pd
|
||||
import xlsxwriter
|
||||
import tempfile
|
||||
import oss2
|
||||
from django.conf import settings
|
||||
|
||||
# third party imports
|
||||
from rest_framework.viewsets import GenericViewSet
|
||||
@ -25,7 +22,7 @@ from django.db.models.functions.window import Rank
|
||||
from django.http import HttpResponse
|
||||
|
||||
# local imports
|
||||
from account.utils import custom_response
|
||||
from account.utils import custom_response, get_user_full_name
|
||||
from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, EXPIRED, DATE_FORMAT, TASK_STATUS
|
||||
from guardian.models import JuniorTask
|
||||
from guardian.utils import upload_excel_file_to_alibaba
|
||||
@ -33,7 +30,7 @@ from junior.models import JuniorPoints
|
||||
from web_admin.pagination import CustomPageNumberPagination
|
||||
from web_admin.permission import AdminPermission
|
||||
from web_admin.serializers.analytics_serializer import LeaderboardSerializer, UserCSVReportSerializer
|
||||
from web_admin.serializers.user_management_serializer import UserManagementListSerializer
|
||||
from web_admin.utils import get_dates
|
||||
|
||||
USER = get_user_model()
|
||||
|
||||
@ -56,7 +53,7 @@ class AnalyticsViewSet(GenericViewSet):
|
||||
).prefetch_related('guardian_profile',
|
||||
'junior_profile'
|
||||
).exclude(junior_profile__isnull=True,
|
||||
guardian_profile__isnull=True).order_by('date_joined')
|
||||
guardian_profile__isnull=True).order_by('-date_joined')
|
||||
return user_qs
|
||||
|
||||
@action(methods=['get'], url_name='users-count', url_path='users-count', detail=False)
|
||||
@ -67,13 +64,8 @@ class AnalyticsViewSet(GenericViewSet):
|
||||
:param request: end_date: date format (yyyy-mm-dd)
|
||||
:return:
|
||||
"""
|
||||
|
||||
end_date = datetime.date.today()
|
||||
start_date = end_date - datetime.timedelta(days=6)
|
||||
|
||||
if request.query_params.get('start_date') and request.query_params.get('end_date'):
|
||||
start_date = datetime.datetime.strptime(request.query_params.get('start_date'), DATE_FORMAT)
|
||||
end_date = datetime.datetime.strptime(request.query_params.get('end_date'), DATE_FORMAT)
|
||||
start_date, end_date = get_dates(request.query_params.get('start_date'),
|
||||
request.query_params.get('end_date'))
|
||||
|
||||
user_qs = self.get_queryset()
|
||||
queryset = user_qs.filter(date_joined__range=(start_date, (end_date + datetime.timedelta(days=1))))
|
||||
@ -92,12 +84,8 @@ class AnalyticsViewSet(GenericViewSet):
|
||||
:param request: end_date: date format (yyyy-mm-dd)
|
||||
:return:
|
||||
"""
|
||||
end_date = datetime.date.today()
|
||||
start_date = end_date - datetime.timedelta(days=6)
|
||||
|
||||
if request.query_params.get('start_date') and request.query_params.get('end_date'):
|
||||
start_date = datetime.datetime.strptime(request.query_params.get('start_date'), DATE_FORMAT)
|
||||
end_date = datetime.datetime.strptime(request.query_params.get('end_date'), DATE_FORMAT)
|
||||
start_date, end_date = get_dates(request.query_params.get('start_date'),
|
||||
request.query_params.get('end_date'))
|
||||
|
||||
user_qs = self.get_queryset()
|
||||
signup_data = user_qs.filter(date_joined__range=[start_date, (end_date + datetime.timedelta(days=1))]
|
||||
@ -114,22 +102,20 @@ class AnalyticsViewSet(GenericViewSet):
|
||||
:param request: end_date: date format (yyyy-mm-dd)
|
||||
:return:
|
||||
"""
|
||||
end_date = datetime.date.today()
|
||||
start_date = end_date - datetime.timedelta(days=6)
|
||||
|
||||
if request.query_params.get('start_date') and request.query_params.get('end_date'):
|
||||
start_date = datetime.datetime.strptime(request.query_params.get('start_date'), DATE_FORMAT)
|
||||
end_date = datetime.datetime.strptime(request.query_params.get('end_date'), DATE_FORMAT)
|
||||
start_date, end_date = get_dates(request.query_params.get('start_date'),
|
||||
request.query_params.get('end_date'))
|
||||
|
||||
assign_tasks = JuniorTask.objects.filter(
|
||||
created_at__range=[start_date, (end_date + datetime.timedelta(days=1))]
|
||||
).exclude(task_status__in=[PENDING, EXPIRED])
|
||||
)
|
||||
|
||||
data = {
|
||||
'task_completed': assign_tasks.filter(task_status=COMPLETED).count(),
|
||||
'task_pending': assign_tasks.filter(task_status=PENDING).count(),
|
||||
'task_in_progress': assign_tasks.filter(task_status=IN_PROGRESS).count(),
|
||||
'task_requested': assign_tasks.filter(task_status=REQUESTED).count(),
|
||||
'task_rejected': assign_tasks.filter(task_status=REJECTED).count(),
|
||||
'task_expired': assign_tasks.filter(task_status=EXPIRED).count(),
|
||||
}
|
||||
|
||||
return custom_response(None, data)
|
||||
@ -163,12 +149,8 @@ class AnalyticsViewSet(GenericViewSet):
|
||||
response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
|
||||
response['Content-Disposition'] = 'attachment; filename="ZOD_Bank_Analytics.xlsx"'
|
||||
|
||||
end_date = datetime.date.today()
|
||||
start_date = end_date - datetime.timedelta(days=6)
|
||||
|
||||
if request.query_params.get('start_date') and request.query_params.get('end_date'):
|
||||
start_date = datetime.datetime.strptime(request.query_params.get('start_date'), DATE_FORMAT)
|
||||
end_date = datetime.datetime.strptime(request.query_params.get('end_date'), DATE_FORMAT)
|
||||
start_date, end_date = get_dates(request.query_params.get('start_date'),
|
||||
request.query_params.get('end_date'))
|
||||
|
||||
# Use BytesIO for binary data
|
||||
buffer = io.BytesIO()
|
||||
@ -177,7 +159,7 @@ class AnalyticsViewSet(GenericViewSet):
|
||||
workbook = xlsxwriter.Workbook(buffer)
|
||||
|
||||
# Add sheets
|
||||
sheets = ['Users', 'Assign Tasks', 'Juniors leaderboard']
|
||||
sheets = ['Users', 'Assign Tasks', 'Juniors Leaderboard']
|
||||
|
||||
for sheet_name in sheets:
|
||||
worksheet = workbook.add_worksheet(name=sheet_name)
|
||||
@ -189,59 +171,48 @@ class AnalyticsViewSet(GenericViewSet):
|
||||
serializer = UserCSVReportSerializer(queryset, many=True)
|
||||
|
||||
df_users = pd.DataFrame([
|
||||
{'Name': f"{user['first_name']} {user['last_name']}",
|
||||
'Email': user['email'], 'Phone Number': user['phone_number'],
|
||||
'User Type': user['user_type'], 'Status': user['is_active'],
|
||||
'Date Joined': user['date_joined']}
|
||||
{'Name': user['name'], 'Email': user['email'],
|
||||
'Phone Number': user['phone_number'], 'User Type': user['user_type'],
|
||||
'Status': user['is_active'], 'Date Joined': user['date_joined']}
|
||||
for user in serializer.data
|
||||
])
|
||||
for idx, col in enumerate(df_users.columns):
|
||||
# Write header
|
||||
worksheet.write(0, idx, col)
|
||||
for row_num, row in enumerate(df_users.values, start=1):
|
||||
for col_num, value in enumerate(row):
|
||||
worksheet.write(row_num, col_num, value)
|
||||
write_excel_worksheet(worksheet, df_users)
|
||||
|
||||
# sheet 2 for Assign Task
|
||||
elif sheet_name == 'Assign Tasks':
|
||||
assign_tasks = JuniorTask.objects.filter(
|
||||
created_at__range=[start_date, (end_date + datetime.timedelta(days=1))]
|
||||
).exclude(task_status__in=[PENDING, EXPIRED])
|
||||
).select_related('junior__auth', 'guardian__user').only('task_name', 'task_status',
|
||||
'junior__auth__first_name',
|
||||
'junior__auth__last_name',
|
||||
'guardian__user__first_name',
|
||||
'guardian__user__last_name',)
|
||||
|
||||
df_tasks = pd.DataFrame([
|
||||
{'Task Name': task.task_name, 'Task Status': dict(TASK_STATUS).get(task.task_status).capitalize()}
|
||||
{'Task Name': task.task_name, 'Assign To': get_user_full_name(task.junior.auth),
|
||||
'Assign By': get_user_full_name(task.guardian.user),
|
||||
'Task Status': dict(TASK_STATUS).get(task.task_status).capitalize()}
|
||||
for task in assign_tasks
|
||||
])
|
||||
|
||||
for idx, col in enumerate(df_tasks.columns):
|
||||
# Write header
|
||||
worksheet.write(0, idx, col)
|
||||
for row_num, row in enumerate(df_tasks.values, start=1):
|
||||
for col_num, value in enumerate(row):
|
||||
worksheet.write(row_num, col_num, value)
|
||||
write_excel_worksheet(worksheet, df_tasks)
|
||||
|
||||
# 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(
|
||||
expression=Rank(),
|
||||
order_by=[F('total_points').desc(), 'junior__created_at']
|
||||
)).order_by('-total_points', 'junior__created_at')[:15]
|
||||
df_leaderboard = pd.DataFrame([
|
||||
{
|
||||
'Junior Name': f"{junior.junior.auth.first_name} {junior.junior.auth.last_name}"
|
||||
if junior.junior.auth.last_name else junior.junior.auth.first_name,
|
||||
'Name': get_user_full_name(junior.junior.auth),
|
||||
'Points': junior.total_points,
|
||||
'Rank': junior.rank
|
||||
}
|
||||
for junior in queryset
|
||||
])
|
||||
|
||||
for idx, col in enumerate(df_leaderboard.columns):
|
||||
# Write header
|
||||
worksheet.write(0, idx, col)
|
||||
for row_num, row in enumerate(df_leaderboard.values, start=1):
|
||||
for col_num, value in enumerate(row):
|
||||
worksheet.write(row_num, col_num, value)
|
||||
write_excel_worksheet(worksheet, df_leaderboard)
|
||||
|
||||
# Close the workbook to save the content
|
||||
workbook.close()
|
||||
@ -255,3 +226,18 @@ class AnalyticsViewSet(GenericViewSet):
|
||||
file_link = upload_excel_file_to_alibaba(response, filename)
|
||||
return custom_response(None, file_link)
|
||||
|
||||
|
||||
def write_excel_worksheet(worksheet, dataframe):
|
||||
"""
|
||||
to perform write action on worksheets
|
||||
:param worksheet:
|
||||
:param dataframe:
|
||||
:return: worksheet
|
||||
"""
|
||||
for idx, col in enumerate(dataframe.columns):
|
||||
# Write header
|
||||
worksheet.write(0, idx, col)
|
||||
for row_num, row in enumerate(dataframe.values, start=1):
|
||||
for col_num, value in enumerate(row):
|
||||
worksheet.write(row_num, col_num, value)
|
||||
return worksheet
|
||||
|
||||
@ -229,7 +229,7 @@ class ArticleListViewSet(GenericViewSet, mixins.ListModelMixin):
|
||||
http_method_names = ['get',]
|
||||
|
||||
def get_queryset(self):
|
||||
article = self.queryset.objects.filter(is_deleted=False).prefetch_related(
|
||||
article = self.queryset.objects.filter(is_deleted=False, is_published=True).prefetch_related(
|
||||
'article_cards', 'article_survey', 'article_survey__options'
|
||||
).order_by('-created_at')
|
||||
queryset = self.filter_queryset(article)
|
||||
@ -248,7 +248,9 @@ class ArticleListViewSet(GenericViewSet, mixins.ListModelMixin):
|
||||
return custom_response(None, data=serializer.data)
|
||||
|
||||
class ArticleCardListViewSet(viewsets.ModelViewSet):
|
||||
"""Junior Points viewset"""
|
||||
"""Article card list
|
||||
use below query param
|
||||
article_id"""
|
||||
serializer_class = ArticleCardlistSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
http_method_names = ('get',)
|
||||
@ -257,7 +259,9 @@ class ArticleCardListViewSet(viewsets.ModelViewSet):
|
||||
"""get queryset"""
|
||||
return ArticleCard.objects.filter(article=self.request.GET.get('article_id'))
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""profile view"""
|
||||
"""Article card list
|
||||
use below query param
|
||||
article_id"""
|
||||
|
||||
try:
|
||||
queryset = self.get_queryset()
|
||||
|
||||
@ -27,6 +27,13 @@ app.config_from_object('django.conf:settings')
|
||||
# Load task modules from all registered Django apps.
|
||||
app.autodiscover_tasks()
|
||||
|
||||
app.conf.beat_schedule = {
|
||||
'notify_task_expiry': {
|
||||
'task': 'base.tasks.notify_task_expiry',
|
||||
'schedule': crontab(minute='0', hour='*/1'),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@app.task(bind=True)
|
||||
def debug_task(self):
|
||||
|
||||
Reference in New Issue
Block a user