diff --git a/account/custom_middleware.py b/account/custom_middleware.py
index 7a06e43..ec2e315 100644
--- a/account/custom_middleware.py
+++ b/account/custom_middleware.py
@@ -7,7 +7,9 @@ from rest_framework.renderers import JSONRenderer
from account.utils import custom_error_response
from account.models import UserDeviceDetails
from base.messages import ERROR_CODE, SUCCESS_CODE
-
+from base.constants import NUMBER
+from junior.models import Junior
+from guardian.models import Guardian
# Custom middleware
# when user login with
# multiple device simultaneously
@@ -15,6 +17,16 @@ from base.messages import ERROR_CODE, SUCCESS_CODE
# multiple devices only
# user can login in single
# device at a time"""
+
+def custom_response(custom_error):
+ """custom response"""
+ response = Response(custom_error.data, status=status.HTTP_404_NOT_FOUND)
+ # Set content type header to "application/json"
+ response['Content-Type'] = 'application/json'
+ # Render the response as JSON
+ renderer = JSONRenderer()
+ response.content = renderer.render(response.data)
+ return response
class CustomMiddleware(object):
"""Custom middleware"""
def __init__(self, get_response):
@@ -26,15 +38,21 @@ class CustomMiddleware(object):
response = self.get_response(request)
# 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')
if request.user.is_authenticated:
"""device details"""
device_details = UserDeviceDetails.objects.filter(user=request.user, device_id=device_id).last()
+ if user_type and str(user_type) == str(NUMBER['one']):
+ junior = Junior.objects.filter(auth=request.user, is_active=False).last()
+ if junior:
+ custom_error = custom_error_response(ERROR_CODE['2075'], response_status=status.HTTP_404_NOT_FOUND)
+ response = custom_response(custom_error)
+ elif user_type and str(user_type) == str(NUMBER['two']):
+ guardian = Guardian.objects.filter(user=request.user, is_active=False).last()
+ if guardian:
+ custom_error = custom_error_response(ERROR_CODE['2075'], response_status=status.HTTP_404_NOT_FOUND)
+ response = custom_response(custom_error)
if device_id and not device_details:
custom_error = custom_error_response(ERROR_CODE['2037'], response_status=status.HTTP_404_NOT_FOUND)
- response = Response(custom_error.data, status=status.HTTP_404_NOT_FOUND)
- # Set content type header to "application/json"
- response['Content-Type'] = 'application/json'
- # Render the response as JSON
- renderer = JSONRenderer()
- response.content = renderer.render(response.data)
+ response = custom_response(custom_error)
return response
diff --git a/account/serializers.py b/account/serializers.py
index ebdc263..0caeb8c 100644
--- a/account/serializers.py
+++ b/account/serializers.py
@@ -244,7 +244,7 @@ class GuardianSerializer(serializers.ModelSerializer):
"""Meta info"""
model = Guardian
fields = ['id', 'auth_token', 'refresh_token', 'email', 'first_name', 'last_name', 'country_code',
- 'phone', 'family_name', 'gender', 'dob', 'referral_code', 'is_active',
+ 'phone', 'family_name', 'gender', 'dob', 'referral_code', 'is_active', 'is_deleted',
'is_complete_profile', 'passcode', 'image', 'created_at', 'updated_at', 'user_type', 'country_name']
@@ -287,7 +287,8 @@ class JuniorSerializer(serializers.ModelSerializer):
model = Junior
fields = ['id', 'auth_token', 'refresh_token', 'email', 'first_name', 'last_name', 'country_code',
'phone', 'gender', 'dob', 'guardian_code', 'referral_code','is_active', 'is_password_set',
- 'is_complete_profile', 'created_at', 'image', 'updated_at', 'user_type', 'country_name','is_invited']
+ 'is_complete_profile', 'created_at', 'image', 'updated_at', 'user_type', 'country_name','is_invited',
+ 'is_deleted']
class EmailVerificationSerializer(serializers.ModelSerializer):
"""Email verification serializer"""
diff --git a/account/templates/templated_email/support_mail.email b/account/templates/templated_email/support_mail.email
index 50467a9..34d6156 100644
--- a/account/templates/templated_email/support_mail.email
+++ b/account/templates/templated_email/support_mail.email
@@ -8,14 +8,14 @@
- Hi {{name}},
+ Hi Support Team,
|
- {{name}} have some queries and need some support. Please support them by using their email address {{sender}}. Queries are:- {{ message }}
+ {{name}} have some queries and need some support. Please support them by using their email address {{sender}}. Queries are:-
{{ message }}
|
diff --git a/account/utils.py b/account/utils.py
index 8df5294..e016940 100644
--- a/account/utils.py
+++ b/account/utils.py
@@ -95,6 +95,7 @@ def junior_account_update(user_tb):
junior_data.is_verified = False
junior_data.guardian_code = '{}'
junior_data.guardian_code_status = str(NUMBER['one'])
+ junior_data.is_deleted = True
junior_data.save()
JuniorPoints.objects.filter(junior=junior_data).delete()
@@ -105,6 +106,7 @@ def guardian_account_update(user_tb):
# Update guardian account
guardian_data.is_active = False
guardian_data.is_verified = False
+ guardian_data.is_deleted = True
guardian_data.save()
jun_data = Junior.objects.filter(guardian_code__icontains=str(guardian_data.guardian_code))
"""Disassociate relation between guardian and junior"""
diff --git a/account/views.py b/account/views.py
index c17f853..f91f1fe 100644
--- a/account/views.py
+++ b/account/views.py
@@ -287,7 +287,7 @@ class UserLogin(viewsets.ViewSet):
def login(self, request):
username = request.data.get('username')
password = request.data.get('password')
- user_type = request.data.get('user_type')
+ user_type = request.META.get('HTTP_USER_TYPE')
device_id = request.META.get('HTTP_DEVICE_ID')
user = authenticate(request, username=username, password=password)
diff --git a/base/messages.py b/base/messages.py
index 10fbfaa..cbcd559 100644
--- a/base/messages.py
+++ b/base/messages.py
@@ -96,9 +96,12 @@ ERROR_CODE = {
"2067": "Action not allowed. User type missing.",
"2068": "No guardian associated with this junior",
"2069": "Invalid user type",
- "2070": "You did not find as a guardian",
- "2071": "You did not find as a junior"
-
+ "2070": "You do not find as a guardian",
+ "2071": "You do not find as a junior",
+ "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"
}
"""Success message code"""
SUCCESS_CODE = {
@@ -163,6 +166,8 @@ SUCCESS_CODE = {
"3043": "Read article card successfully",
# remove guardian code request
"3044": "Remove guardian code request successfully",
+ # create faq
+ "3045": "Create FAQ data"
}
"""status code error"""
diff --git a/celerybeat-schedule b/celerybeat-schedule
index ce5d8ac..4a3bd31 100644
Binary files a/celerybeat-schedule and b/celerybeat-schedule differ
diff --git a/guardian/migrations/0021_guardian_is_deleted.py b/guardian/migrations/0021_guardian_is_deleted.py
new file mode 100644
index 0000000..11833c6
--- /dev/null
+++ b/guardian/migrations/0021_guardian_is_deleted.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.2 on 2023-08-17 12:45
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('guardian', '0020_alter_juniortask_task_status'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='guardian',
+ name='is_deleted',
+ field=models.BooleanField(default=False),
+ ),
+ ]
diff --git a/guardian/models.py b/guardian/models.py
index 45afee7..5c6457a 100644
--- a/guardian/models.py
+++ b/guardian/models.py
@@ -57,6 +57,8 @@ class Guardian(models.Model):
is_invited = models.BooleanField(default=False)
# Profile activity"""
is_password_set = models.BooleanField(default=True)
+ # guardian profile deleted or not"""
+ is_deleted = models.BooleanField(default=False)
"""Profile activity"""
is_active = models.BooleanField(default=True)
"""guardian is verified or not"""
diff --git a/guardian/serializers.py b/guardian/serializers.py
index cbd1e4e..f36bd46 100644
--- a/guardian/serializers.py
+++ b/guardian/serializers.py
@@ -1,6 +1,7 @@
"""Serializer of Guardian"""
# third party imports
import logging
+from django.contrib.auth import password_validation
from rest_framework import serializers
# Import Refresh token of jwt
from rest_framework_simplejwt.tokens import RefreshToken
@@ -30,7 +31,8 @@ from .utils import real_time, convert_timedelta_into_datetime, update_referral_p
from notifications.constants import TASK_POINTS, TASK_REJECTED
# send notification function
from notifications.utils import send_notification, send_notification_to_junior
-
+from django.core.exceptions import ValidationError
+from django.utils.translation import gettext as _
# In this serializer file
# define user serializer,
@@ -42,10 +44,45 @@ from notifications.utils import send_notification, send_notification_to_junior
# guardian profile serializer,
# approve junior serializer,
# approve task serializer,
+from rest_framework import serializers
+
+class PasswordValidator:
+ def __init__(self, min_length=8, max_length=None, require_uppercase=True, require_numbers=True):
+ self.min_length = min_length
+ self.max_length = max_length
+ self.require_uppercase = require_uppercase
+ self.require_numbers = require_numbers
+
+ def __call__(self, value):
+ self.enforce_password_policy(value)
+
+ def enforce_password_policy(self, password):
+ special_characters = "!@#$%^&*()_-+=<>?/[]{}|"
+ if len(password) < self.min_length:
+ raise serializers.ValidationError(
+ _("Password must be at least %(min_length)d characters long.") % {'min_length': self.min_length}
+ )
+
+ if self.max_length is not None and len(password) > self.max_length:
+ raise serializers.ValidationError(
+ _("Password must be at most %(max_length)d characters long.") % {'max_length': self.max_length}
+ )
+
+ if self.require_uppercase and not any(char.isupper() for char in password):
+ raise serializers.ValidationError(_("Password must contain at least one uppercase letter."))
+
+ if self.require_numbers and not any(char.isdigit() for char in password):
+ raise serializers.ValidationError(_("Password must contain at least one digit."))
+ if self.require_numbers and not any(char in special_characters for char in password):
+ raise serializers.ValidationError(_("Password must contain at least one special character."))
+
+
+
class UserSerializer(serializers.ModelSerializer):
"""User serializer"""
auth_token = serializers.SerializerMethodField('get_auth_token')
+ password = serializers.CharField(write_only=True, validators=[PasswordValidator()])
class Meta(object):
"""Meta info"""
@@ -214,7 +251,7 @@ class GuardianDetailSerializer(serializers.ModelSerializer):
"""Meta info"""
model = Guardian
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
- 'guardian_code','is_active', 'is_complete_profile', 'created_at', 'image',
+ 'guardian_code','is_active', 'is_complete_profile', 'created_at', 'image', 'is_deleted'
'updated_at']
class TaskDetailsSerializer(serializers.ModelSerializer):
"""Task detail serializer"""
@@ -340,7 +377,7 @@ class GuardianProfileSerializer(serializers.ModelSerializer):
fields = ['id', 'email', 'first_name', 'last_name', 'country_name','country_code', 'phone', 'gender', 'dob',
'guardian_code', 'notification_count', 'total_count', 'complete_field_count', 'referral_code',
'is_active', 'is_complete_profile', 'created_at', 'image', 'signup_method',
- 'updated_at', 'passcode']
+ 'updated_at', 'passcode','is_deleted']
class ApproveJuniorSerializer(serializers.ModelSerializer):
diff --git a/guardian/views.py b/guardian/views.py
index 67fe6ef..fc52a8e 100644
--- a/guardian/views.py
+++ b/guardian/views.py
@@ -255,31 +255,29 @@ class ApproveJuniorAPIView(viewsets.ViewSet):
serializer_class = ApproveJuniorSerializer
permission_classes = [IsAuthenticated]
- def get_queryset(self):
- """Get the queryset for the view"""
- guardian = Guardian.objects.filter(user__email=self.request.user).last()
- # fetch junior query
- junior_queryset = Junior.objects.filter(id=self.request.data.get('junior_id')).last()
- return guardian, junior_queryset
def create(self, request, *args, **kwargs):
""" junior list"""
try:
- queryset = self.get_queryset()
+ guardian = Guardian.objects.filter(user__email=self.request.user).last()
+ # fetch junior query
+ junior_queryset = Junior.objects.filter(id=self.request.data.get('junior_id')).last()
+ if junior_queryset and junior_queryset.is_deleted:
+ return custom_error_response(ERROR_CODE['2073'], response_status=status.HTTP_400_BAD_REQUEST)
# action 1 is use for approve and 2 for reject
if request.data['action'] == '1':
# use ApproveJuniorSerializer serializer
- serializer = ApproveJuniorSerializer(context={"guardian_code": queryset[0].guardian_code,
- "junior": queryset[1], "action": request.data['action']},
+ serializer = ApproveJuniorSerializer(context={"guardian_code": guardian.guardian_code,
+ "junior": junior_queryset, "action": request.data['action']},
data=request.data)
if serializer.is_valid():
# save serializer
serializer.save()
return custom_response(SUCCESS_CODE['3023'], serializer.data, response_status=status.HTTP_200_OK)
else:
- queryset[1].guardian_code = None
- queryset[1].guardian_code_status = str(NUMBER['one'])
- queryset[1].save()
+ junior_queryset.guardian_code = None
+ junior_queryset.guardian_code_status = str(NUMBER['one'])
+ junior_queryset.save()
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)
@@ -290,34 +288,31 @@ class ApproveTaskAPIView(viewsets.ViewSet):
serializer_class = ApproveTaskSerializer
permission_classes = [IsAuthenticated]
- def get_queryset(self):
- """Get the queryset for the view"""
- guardian = Guardian.objects.filter(user__email=self.request.user).last()
- # task query
- task_queryset = JuniorTask.objects.filter(id=self.request.data.get('task_id'),
- guardian=guardian,
- junior=self.request.data.get('junior_id')).last()
- return guardian, task_queryset
-
def create(self, request, *args, **kwargs):
""" junior list"""
# action 1 is use for approve and 2 for reject
try:
- queryset = self.get_queryset()
+ guardian = Guardian.objects.filter(user__email=self.request.user).last()
+ # task query
+ task_queryset = JuniorTask.objects.filter(id=self.request.data.get('task_id'),
+ guardian=guardian,
+ junior=self.request.data.get('junior_id')).last()
+ if task_queryset and task_queryset.junior.is_deleted:
+ return custom_error_response(ERROR_CODE['2072'], response_status=status.HTTP_400_BAD_REQUEST)
# use ApproveJuniorSerializer serializer
- serializer = ApproveTaskSerializer(context={"guardian_code": queryset[0].guardian_code,
- "task_instance": queryset[1],
+ serializer = ApproveTaskSerializer(context={"guardian_code": guardian.guardian_code,
+ "task_instance": task_queryset,
"action": str(request.data['action']),
"junior": self.request.data['junior_id']},
data=request.data)
unexpected_task_status = [str(NUMBER['five']), str(NUMBER['six'])]
if (str(request.data['action']) == str(NUMBER['one']) and serializer.is_valid()
- and queryset[1] and queryset[1].task_status not in unexpected_task_status):
+ and task_queryset and task_queryset.task_status not in unexpected_task_status):
# save serializer
serializer.save()
return custom_response(SUCCESS_CODE['3025'], response_status=status.HTTP_200_OK)
elif (str(request.data['action']) == str(NUMBER['two']) and serializer.is_valid()
- and queryset[1] and queryset[1].task_status not in unexpected_task_status):
+ and task_queryset and task_queryset.task_status not in unexpected_task_status):
# save serializer
serializer.save()
return custom_response(SUCCESS_CODE['3026'], response_status=status.HTTP_200_OK)
diff --git a/junior/admin.py b/junior/admin.py
index 6c6cdf9..2ffda51 100644
--- a/junior/admin.py
+++ b/junior/admin.py
@@ -3,8 +3,9 @@
from django.contrib import admin
"""Import Django app"""
from .models import (Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints, JuniorArticle,
- JuniorArticleCard)
+ JuniorArticleCard, FAQ)
# Register your models here.
+admin.site.register(FAQ)
@admin.register(JuniorArticle)
class JuniorArticleAdmin(admin.ModelAdmin):
"""Junior Admin"""
diff --git a/junior/migrations/0026_faq_alter_juniorarticle_options_and_more.py b/junior/migrations/0026_faq_alter_juniorarticle_options_and_more.py
new file mode 100644
index 0000000..12243a2
--- /dev/null
+++ b/junior/migrations/0026_faq_alter_juniorarticle_options_and_more.py
@@ -0,0 +1,39 @@
+# Generated by Django 4.2.2 on 2023-08-17 09:04
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('junior', '0025_alter_juniorarticle_junior'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='FAQ',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('question', models.IntegerField(max_length=100)),
+ ('description', models.CharField(max_length=500)),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('updated_at', models.DateTimeField(auto_now=True)),
+ ],
+ options={
+ 'verbose_name': 'FAQ',
+ 'verbose_name_plural': 'FAQ',
+ },
+ ),
+ migrations.AlterModelOptions(
+ name='juniorarticle',
+ options={'verbose_name': 'Junior Article', 'verbose_name_plural': 'Junior Article'},
+ ),
+ migrations.AlterModelOptions(
+ name='juniorarticlecard',
+ options={'verbose_name': 'Junior Article Card', 'verbose_name_plural': 'Junior Article Card'},
+ ),
+ migrations.AlterModelOptions(
+ name='juniorarticlepoints',
+ options={'verbose_name': 'Junior Article Points', 'verbose_name_plural': 'Junior Article Points'},
+ ),
+ ]
diff --git a/junior/migrations/0027_alter_faq_question.py b/junior/migrations/0027_alter_faq_question.py
new file mode 100644
index 0000000..46fefd8
--- /dev/null
+++ b/junior/migrations/0027_alter_faq_question.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.2 on 2023-08-17 09:37
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('junior', '0026_faq_alter_juniorarticle_options_and_more'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='faq',
+ name='question',
+ field=models.CharField(max_length=100),
+ ),
+ ]
diff --git a/junior/migrations/0028_faq_status.py b/junior/migrations/0028_faq_status.py
new file mode 100644
index 0000000..bdfbf67
--- /dev/null
+++ b/junior/migrations/0028_faq_status.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.2 on 2023-08-17 10:28
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('junior', '0027_alter_faq_question'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='faq',
+ name='status',
+ field=models.IntegerField(blank=True, default=1, null=True),
+ ),
+ ]
diff --git a/junior/migrations/0029_junior_is_deleted.py b/junior/migrations/0029_junior_is_deleted.py
new file mode 100644
index 0000000..a39f60f
--- /dev/null
+++ b/junior/migrations/0029_junior_is_deleted.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.2 on 2023-08-17 12:45
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('junior', '0028_faq_status'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='junior',
+ name='is_deleted',
+ field=models.BooleanField(default=False),
+ ),
+ ]
diff --git a/junior/models.py b/junior/models.py
index 025843e..773557b 100644
--- a/junior/models.py
+++ b/junior/models.py
@@ -68,6 +68,8 @@ class Junior(models.Model):
is_password_set = models.BooleanField(default=True)
# junior profile is complete or not"""
is_complete_profile = models.BooleanField(default=False)
+ # junior profile deleted or not"""
+ is_deleted = models.BooleanField(default=False)
# passcode of the junior profile"""
passcode = models.IntegerField(null=True, blank=True, default=None)
# junior is verified or not"""
@@ -158,6 +160,12 @@ class JuniorArticlePoints(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
+ class Meta(object):
+ """ Meta class """
+ verbose_name = 'Junior Article Points'
+ # another name of the model"""
+ verbose_name_plural = 'Junior Article Points'
+
def __str__(self):
"""Return title"""
return f'{self.id} | {self.question}'
@@ -178,6 +186,12 @@ class JuniorArticle(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
+ class Meta(object):
+ """ Meta class """
+ verbose_name = 'Junior Article'
+ # another name of the model"""
+ verbose_name_plural = 'Junior Article'
+
def __str__(self):
"""Return title"""
return f'{self.id} | {self.article}'
@@ -197,6 +211,34 @@ class JuniorArticleCard(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
+ class Meta(object):
+ """ Meta class """
+ verbose_name = 'Junior Article Card'
+ # another name of the model"""
+ verbose_name_plural = 'Junior Article Card'
+
def __str__(self):
"""Return title"""
return f'{self.id} | {self.article}'
+
+
+class FAQ(models.Model):
+ """FAQ model"""
+ # questions"""
+ question = models.CharField(max_length=100)
+ # answer"""
+ description = models.CharField(max_length=500)
+ # status
+ status = models.IntegerField(default=1, null=True, blank=True)
+ created_at = models.DateTimeField(auto_now_add=True)
+ updated_at = models.DateTimeField(auto_now=True)
+
+ class Meta(object):
+ """ Meta class """
+ verbose_name = 'FAQ'
+ # another name of the model"""
+ verbose_name_plural = 'FAQ'
+
+ def __str__(self):
+ """Return email id"""
+ return f'{self.question}'
diff --git a/junior/serializers.py b/junior/serializers.py
index f932a26..b4aa54f 100644
--- a/junior/serializers.py
+++ b/junior/serializers.py
@@ -12,7 +12,7 @@ from rest_framework_simplejwt.tokens import RefreshToken
# local imports
from account.utils import send_otp_email, generate_code
-from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints
+from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints, FAQ
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,
@@ -147,7 +147,7 @@ class JuniorDetailSerializer(serializers.ModelSerializer):
model = Junior
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
'guardian_code', 'image', 'is_invited', 'referral_code','is_active', 'is_complete_profile',
- 'created_at', 'image', 'updated_at']
+ 'created_at', 'image', 'is_deleted', 'updated_at']
class JuniorDetailListSerializer(serializers.ModelSerializer):
"""junior serializer"""
@@ -214,7 +214,8 @@ class JuniorDetailListSerializer(serializers.ModelSerializer):
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'country_name', 'phone', 'gender', 'dob',
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
'updated_at', 'assigned_task','points', 'pending_task', 'in_progress_task', 'completed_task',
- 'requested_task', 'rejected_task', 'position', 'is_invited', 'guardian_code_status']
+ 'requested_task', 'rejected_task', 'position', 'is_invited', 'guardian_code_status',
+ 'is_deleted']
class JuniorProfileSerializer(serializers.ModelSerializer):
"""junior serializer"""
@@ -257,7 +258,7 @@ class JuniorProfileSerializer(serializers.ModelSerializer):
fields = ['id', 'email', 'first_name', 'last_name', 'country_name', 'country_code', 'phone', 'gender', 'dob',
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
'updated_at', 'notification_count', 'total_count', 'complete_field_count', 'signup_method',
- 'is_invited', 'passcode', 'guardian_code_approved']
+ 'is_invited', 'passcode', 'guardian_code_approved', 'is_deleted']
class AddJuniorSerializer(serializers.ModelSerializer):
"""Add junior serializer"""
@@ -395,7 +396,7 @@ class JuniorPointsSerializer(serializers.ModelSerializer):
"""Meta info"""
model = Junior
fields = ['junior_id', 'total_points', 'position', 'pending_task', 'in_progress_task', 'completed_task',
- 'requested_task', 'rejected_task', 'expired_task']
+ 'requested_task', 'rejected_task', 'expired_task', 'is_deleted']
class AddGuardianSerializer(serializers.ModelSerializer):
"""Add guardian serializer"""
@@ -508,3 +509,12 @@ class RemoveGuardianCodeSerializer(serializers.ModelSerializer):
instance.guardian_code_status = str(NUMBER['one'])
instance.save()
return instance
+
+class FAQSerializer(serializers.ModelSerializer):
+ # FAQ Serializer
+
+ class Meta(object):
+ # meta info
+ model = FAQ
+ fields = ('id', 'question', 'description')
+
diff --git a/junior/urls.py b/junior/urls.py
index b145d4f..08fe33a 100644
--- a/junior/urls.py
+++ b/junior/urls.py
@@ -6,7 +6,7 @@ from .views import (UpdateJuniorProfile, ValidateGuardianCode, JuniorListAPIView
CompleteJuniorTaskAPIView, JuniorPointsListAPIView, ValidateReferralCode,
InviteGuardianAPIView, StartTaskAPIView, ReAssignJuniorTaskAPIView, StartArticleAPIView,
StartAssessmentAPIView, CheckAnswerAPIView, CompleteArticleAPIView, ReadArticleCardAPIView,
- CreateArticleCardAPIView, RemoveGuardianCodeAPIView)
+ CreateArticleCardAPIView, RemoveGuardianCodeAPIView, FAQViewSet)
"""Third party import"""
from rest_framework import routers
@@ -51,6 +51,8 @@ router.register('start-assessment', StartAssessmentAPIView, basename='start-asse
router.register('check-answer', CheckAnswerAPIView, basename='check-answer')
# start article"""
router.register('create-article-card', CreateArticleCardAPIView, basename='create-article-card')
+# FAQ API
+router.register('faq', FAQViewSet, basename='faq')
# Define url pattern"""
urlpatterns = [
path('api/v1/', include(router.urls)),
diff --git a/junior/views.py b/junior/views.py
index 6b8bc2f..7a83b0a 100644
--- a/junior/views.py
+++ b/junior/views.py
@@ -10,6 +10,8 @@ from django.db.models import F
import datetime
import requests
+
+from rest_framework.viewsets import GenericViewSet, mixins
"""Django app import"""
# Import guardian's model,
@@ -30,11 +32,11 @@ import requests
# Import constants
from django.db.models import Sum
from junior.models import (Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints, JuniorArticle,
- JuniorArticleCard)
+ JuniorArticleCard, FAQ)
from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer,
RemoveJuniorSerializer, CompleteTaskSerializer, JuniorPointsSerializer,
AddGuardianSerializer, StartTaskSerializer, ReAssignTaskSerializer,
- RemoveGuardianCodeSerializer)
+ RemoveGuardianCodeSerializer, FAQSerializer)
from guardian.models import Guardian, JuniorTask
from guardian.serializers import TaskDetailsSerializer, TaskDetailsjuniorSerializer
from base.messages import ERROR_CODE, SUCCESS_CODE
@@ -337,6 +339,8 @@ class CompleteJuniorTaskAPIView(views.APIView):
task_queryset = JuniorTask.objects.filter(id=task_id, junior__auth__email=self.request.user
).select_related('guardian', 'junior').last()
if task_queryset:
+ if task_queryset.junior.is_deleted:
+ return custom_error_response(ERROR_CODE['2074'], response_status=status.HTTP_400_BAD_REQUEST)
# use CompleteTaskSerializer serializer
if task_queryset.task_status in [str(NUMBER['four']), str(NUMBER['five'])]:
"""Already request send """
@@ -650,3 +654,49 @@ class RemoveGuardianCodeAPIView(views.APIView):
return custom_error_response(ERROR_CODE['2047'], 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 FAQViewSet(GenericViewSet, mixins.CreateModelMixin,
+ mixins.ListModelMixin):
+ """FAQ view set"""
+
+ serializer_class = FAQSerializer
+ permission_classes = [IsAuthenticated]
+ http_method_names = ['get', 'post']
+
+ def get_queryset(self):
+ return FAQ.objects.all()
+
+ def create(self, request, *args, **kwargs):
+ """
+ faq create api method
+ :param request:
+ :param args:
+ :param kwargs:
+ :return: success message
+ """
+ obj_data = [FAQ(**item) for item in request.data]
+ try:
+ FAQ.objects.bulk_create(obj_data)
+ return custom_response(SUCCESS_CODE["3045"], response_status=status.HTTP_200_OK)
+ except Exception as e:
+ return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
+
+
+ def list(self, request, *args, **kwargs):
+ """
+ article list api method
+ :param request:
+ :param args:
+ :param kwargs:
+ :return: list of article
+ """
+ queryset = self.get_queryset()
+ paginator = self.pagination_class()
+ paginated_queryset = paginator.paginate_queryset(queryset, request)
+ serializer = self.serializer_class(paginated_queryset, many=True)
+ return custom_response(None, data=serializer.data, response_status=status.HTTP_200_OK)
+
+
+
+
diff --git a/web_admin/serializers/analytics_serializer.py b/web_admin/serializers/analytics_serializer.py
index ce6c72e..0e3418a 100644
--- a/web_admin/serializers/analytics_serializer.py
+++ b/web_admin/serializers/analytics_serializer.py
@@ -28,7 +28,7 @@ class JuniorLeaderboardSerializer(serializers.ModelSerializer):
meta class
"""
model = Junior
- fields = ('id', 'name', 'first_name', 'last_name', 'is_active', 'image')
+ fields = ('id', 'name', 'first_name', 'last_name', 'is_active', 'image', 'is_deleted')
@staticmethod
def get_name(obj):
diff --git a/web_admin/serializers/user_management_serializer.py b/web_admin/serializers/user_management_serializer.py
index 3544c66..21a0a3b 100644
--- a/web_admin/serializers/user_management_serializer.py
+++ b/web_admin/serializers/user_management_serializer.py
@@ -108,7 +108,7 @@ class GuardianSerializer(serializers.ModelSerializer):
"""
model = Guardian
fields = ('id', 'name', 'first_name', 'last_name', 'username', 'dob', 'gender', 'country_code', 'phone',
- 'is_active', 'country_name', 'image', 'email')
+ 'is_active', 'country_name', 'image', 'email', 'is_deleted')
def validate(self, attrs):
"""
@@ -187,7 +187,7 @@ class JuniorSerializer(serializers.ModelSerializer):
"""
model = Junior
fields = ('id', 'name', 'first_name', 'last_name', 'username', 'dob', 'gender', 'country_code', 'phone',
- 'is_active', 'country_name', 'image', 'email')
+ 'is_active', 'country_name', 'image', 'email', 'is_deleted')
def validate(self, attrs):
"""