Merge pull request #171 from KiwiTechLLC/sprint4

financial learning section api
This commit is contained in:
dilipshrivastwa-kiwi
2023-08-09 16:44:27 +05:30
committed by GitHub
10 changed files with 211 additions and 13 deletions

View File

@ -76,6 +76,12 @@ GUARDIAN_CODE_STATUS = (
('2', 'exist guardian code'), ('2', 'exist guardian code'),
('3', 'request for guardian code') ('3', 'request for guardian code')
) )
# article status
ARTICLE_STATUS = (
('1', 'read'),
('2', 'in_progress'),
('3', 'completed')
)
# relationship # relationship
RELATIONSHIP = ( RELATIONSHIP = (
('1', 'parent'), ('1', 'parent'),

View File

@ -150,7 +150,13 @@ SUCCESS_CODE = {
"3038": "Status has been changed successfully.", "3038": "Status has been changed successfully.",
# notification read # notification read
"3039": "Notification read successfully", "3039": "Notification read successfully",
"3040": "Start article successfully" "3040": "Start article successfully",
# complete article
"3041": "Article completed successfully",
# submit assessment successfully
"3042": "Assessment completed successfully",
"3043": "Read article card successfully"
} }
"""status code error""" """status code error"""
STATUS_CODE_ERROR = { STATUS_CODE_ERROR = {

View File

@ -387,8 +387,6 @@ class ApproveTaskSerializer(serializers.ModelSerializer):
# reject the task # reject the task
instance.task_status = str(NUMBER['three']) instance.task_status = str(NUMBER['three'])
instance.is_approved = False instance.is_approved = False
# update total task point
junior_data.total_points = junior_data.total_points - instance.points
# update reject time of task # update reject time of task
# instance.rejected_on = real_time() # instance.rejected_on = real_time()
instance.rejected_on = timezone.now().astimezone(pytz.utc) instance.rejected_on = timezone.now().astimezone(pytz.utc)

View File

@ -2,8 +2,26 @@
"""Third party Django app""" """Third party Django app"""
from django.contrib import admin from django.contrib import admin
"""Import Django app""" """Import Django app"""
from .models import Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints from .models import (Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints, JuniorArticle,
JuniorArticleCard)
# Register your models here. # Register your models here.
@admin.register(JuniorArticle)
class JuniorArticleAdmin(admin.ModelAdmin):
"""Junior Admin"""
list_display = ['junior', 'article', 'status', 'is_completed']
def __str__(self):
"""Return email id"""
return self.junior__auth__email
@admin.register(JuniorArticleCard)
class JuniorArticleCardAdmin(admin.ModelAdmin):
"""Junior Admin"""
list_display = ['junior', 'article', 'article_card', 'is_read']
def __str__(self):
"""Return email id"""
return self.junior__auth__email
@admin.register(Junior) @admin.register(Junior)
class JuniorAdmin(admin.ModelAdmin): class JuniorAdmin(admin.ModelAdmin):
"""Junior Admin""" """Junior Admin"""
@ -30,4 +48,4 @@ class JuniorGuardianRelationshipAdmin(admin.ModelAdmin):
@admin.register(JuniorArticlePoints) @admin.register(JuniorArticlePoints)
class JuniorArticlePointsAdmin(admin.ModelAdmin): class JuniorArticlePointsAdmin(admin.ModelAdmin):
"""Junior Admin""" """Junior Admin"""
list_display = ['junior', 'article', 'question', 'submitted_answer'] list_display = ['junior', 'article', 'question', 'submitted_answer', 'is_answer_correct']

View File

@ -0,0 +1,27 @@
# Generated by Django 4.2.2 on 2023-08-09 09:34
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('web_admin', '0004_alter_surveyoption_survey'),
('junior', '0021_alter_juniorarticlepoints_submitted_answer'),
]
operations = [
migrations.CreateModel(
name='JuniorArticle',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_completed', models.BooleanField(default=False)),
('status', models.CharField(blank=True, choices=[('1', 'read'), ('2', 'in_progress'), ('3', 'completed')], default='1', max_length=10, null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='junior_articles_details', to='web_admin.article')),
('junior', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='juniors_article', to='junior.junior', verbose_name='Junior')),
],
),
]

View File

@ -0,0 +1,27 @@
# Generated by Django 4.2.2 on 2023-08-09 10:47
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('web_admin', '0004_alter_surveyoption_survey'),
('junior', '0022_juniorarticle'),
]
operations = [
migrations.CreateModel(
name='JuniorArticleCard',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_read', models.BooleanField(default=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='junior_articles_detail', to='web_admin.article')),
('article_card', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='junior_article_card', to='web_admin.articlecard')),
('junior', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='juniors_article_card', to='junior.junior', verbose_name='Junior')),
],
),
]

View File

@ -6,11 +6,11 @@ from django.contrib.auth import get_user_model
"""Import ArrayField""" """Import ArrayField"""
from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.fields import ArrayField
"""Import django app""" """Import django app"""
from base.constants import GENDERS, SIGNUP_METHODS, RELATIONSHIP, GUARDIAN_CODE_STATUS from base.constants import GENDERS, SIGNUP_METHODS, RELATIONSHIP, GUARDIAN_CODE_STATUS, ARTICLE_STATUS
# Import guardian's model # Import guardian's model
from guardian.models import Guardian from guardian.models import Guardian
# Import web admin's model # Import web admin's model
from web_admin.models import SurveyOption, ArticleSurvey, Article from web_admin.models import SurveyOption, ArticleSurvey, Article, ArticleCard
"""Define User model""" """Define User model"""
User = get_user_model() User = get_user_model()
# Create your models here. # Create your models here.
@ -161,3 +161,38 @@ class JuniorArticlePoints(models.Model):
def __str__(self): def __str__(self):
"""Return title""" """Return title"""
return f'{self.id} | {self.question}' return f'{self.id} | {self.question}'
class JuniorArticle(models.Model):
"""
Survey Options model
"""
# associated junior with the task
junior = models.OneToOneField(Junior, on_delete=models.CASCADE, related_name='juniors_article', verbose_name='Junior')
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='junior_articles_details')
# article completed"""
is_completed = models.BooleanField(default=False)
status = models.CharField(max_length=10, choices=ARTICLE_STATUS, null=True, blank=True, default='1')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
"""Return title"""
return f'{self.id} | {self.article}'
class JuniorArticleCard(models.Model):
"""
Survey Options model
"""
# associated junior with the task
junior = models.ForeignKey(Junior, on_delete=models.CASCADE, related_name='juniors_article_card', verbose_name='Junior')
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='junior_articles_detail')
article_card = models.ForeignKey(ArticleCard, on_delete=models.CASCADE, related_name='junior_article_card')
# article card read"""
is_read = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
"""Return title"""
return f'{self.id} | {self.article}'

View File

@ -12,7 +12,7 @@ from rest_framework_simplejwt.tokens import RefreshToken
# local imports # local imports
from account.utils import send_otp_email, generate_code from account.utils import send_otp_email, generate_code
from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints
from guardian.tasks import generate_otp from guardian.tasks import generate_otp
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import (PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER, JUN, ZOD, EXPIRED, from base.constants import (PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER, JUN, ZOD, EXPIRED,

View File

@ -5,7 +5,8 @@ from .views import (UpdateJuniorProfile, ValidateGuardianCode, JuniorListAPIView
InvitedJuniorAPIView, FilterJuniorAPIView, RemoveJuniorAPIView, JuniorTaskListAPIView, InvitedJuniorAPIView, FilterJuniorAPIView, RemoveJuniorAPIView, JuniorTaskListAPIView,
CompleteJuniorTaskAPIView, JuniorPointsListAPIView, ValidateReferralCode, CompleteJuniorTaskAPIView, JuniorPointsListAPIView, ValidateReferralCode,
InviteGuardianAPIView, StartTaskAPIView, ReAssignJuniorTaskAPIView, StartArticleAPIView, InviteGuardianAPIView, StartTaskAPIView, ReAssignJuniorTaskAPIView, StartArticleAPIView,
StartAssessmentAPIView, CheckAnswerAPIView) StartAssessmentAPIView, CheckAnswerAPIView, CompleteArticleAPIView, ReadArticleCardAPIView,
CreateArticleCardAPIView)
"""Third party import""" """Third party import"""
from rest_framework import routers from rest_framework import routers
@ -48,6 +49,8 @@ router.register('start-article', StartArticleAPIView, basename='start-article')
router.register('start-assessment', StartAssessmentAPIView, basename='start-assessment') router.register('start-assessment', StartAssessmentAPIView, basename='start-assessment')
# check answer api""" # check answer api"""
router.register('check-answer', CheckAnswerAPIView, basename='check-answer') router.register('check-answer', CheckAnswerAPIView, basename='check-answer')
# start article"""
router.register('create-article-card', CreateArticleCardAPIView, basename='create-article-card')
# Define url pattern""" # Define url pattern"""
urlpatterns = [ urlpatterns = [
path('api/v1/', include(router.urls)), path('api/v1/', include(router.urls)),
@ -55,4 +58,6 @@ urlpatterns = [
path('api/v1/complete-task/', CompleteJuniorTaskAPIView.as_view()), path('api/v1/complete-task/', CompleteJuniorTaskAPIView.as_view()),
path('api/v1/start-task/', StartTaskAPIView.as_view()), path('api/v1/start-task/', StartTaskAPIView.as_view()),
path('api/v1/reassign-task/', ReAssignJuniorTaskAPIView.as_view()), path('api/v1/reassign-task/', ReAssignJuniorTaskAPIView.as_view()),
path('api/v1/complete-article/', CompleteArticleAPIView.as_view()),
path('api/v1/read-article-card/', ReadArticleCardAPIView.as_view()),
] ]

View File

@ -28,20 +28,23 @@ import requests
# Import upload_image_to_alibaba # Import upload_image_to_alibaba
# Import custom_response, custom_error_response # Import custom_response, custom_error_response
# Import constants # Import constants
from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints from django.db.models import Sum
from junior.models import (Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints, JuniorArticle,
JuniorArticleCard)
from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer, from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer,
RemoveJuniorSerializer, CompleteTaskSerializer, JuniorPointsSerializer, RemoveJuniorSerializer, CompleteTaskSerializer, JuniorPointsSerializer,
AddGuardianSerializer, StartTaskSerializer, ReAssignTaskSerializer) AddGuardianSerializer, StartTaskSerializer, ReAssignTaskSerializer
)
from guardian.models import Guardian, JuniorTask from guardian.models import Guardian, JuniorTask
from guardian.serializers import TaskDetailsSerializer, TaskDetailsjuniorSerializer from guardian.serializers import TaskDetailsSerializer, TaskDetailsjuniorSerializer
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import NUMBER from base.constants import NUMBER, ARTICLE_STATUS
from account.utils import custom_response, custom_error_response from account.utils import custom_response, custom_error_response
from guardian.utils import upload_image_to_alibaba from guardian.utils import upload_image_to_alibaba
from .utils import update_positions_based_on_points from .utils import update_positions_based_on_points
from notifications.utils import send_notification from notifications.utils import send_notification
from notifications.constants import REMOVE_JUNIOR from notifications.constants import REMOVE_JUNIOR
from web_admin.models import Article, ArticleSurvey, SurveyOption from web_admin.models import Article, ArticleSurvey, SurveyOption, ArticleCard
from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleListSerializer, from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleListSerializer,
StartAssessmentSerializer) StartAssessmentSerializer)
""" Define APIs """ """ Define APIs """
@ -479,6 +482,8 @@ class StartArticleAPIView(viewsets.ModelViewSet):
junior_instance = Junior.objects.filter(auth=self.request.user).last() junior_instance = Junior.objects.filter(auth=self.request.user).last()
article_id = request.data.get('article_id') article_id = request.data.get('article_id')
article_data = Article.objects.filter(id=article_id).last() article_data = Article.objects.filter(id=article_id).last()
if not JuniorArticle.objects.filter(junior=junior_instance, article=article_data).last():
JuniorArticle.objects.create(junior=junior_instance, article=article_data, status=str(NUMBER['two']))
if article_data: if article_data:
question_query = ArticleSurvey.objects.filter(article=article_id) question_query = ArticleSurvey.objects.filter(article=article_id)
for question in question_query: for question in question_query:
@ -545,3 +550,74 @@ class CheckAnswerAPIView(viewsets.ModelViewSet):
return custom_response(None, response_status=status.HTTP_200_OK) return custom_response(None, response_status=status.HTTP_200_OK)
except Exception as e: except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
class CompleteArticleAPIView(views.APIView):
"""Remove junior API"""
permission_classes = [IsAuthenticated]
http_method_names = ('put', 'get',)
def put(self, request, format=None):
try:
article_id = self.request.data.get('article_id')
JuniorArticle.objects.filter(junior__auth=request.user, article__id=article_id).update(
is_completed=True, status=str(NUMBER['three'])
)
return custom_response(SUCCESS_CODE['3041'], response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
def get(self, request, *args, **kwargs):
""" junior list"""
try:
article_id = self.request.GET.get('article_id')
total_earn_points = JuniorArticlePoints.objects.filter(junior__auth=request.user,
article__id=article_id,
is_answer_correct=True).aggregate(
total_earn_points=Sum('earn_points'))['total_earn_points']
data = {"total_earn_points":total_earn_points}
return custom_response(SUCCESS_CODE['3042'], data, response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
class ReadArticleCardAPIView(views.APIView):
"""Remove junior API"""
permission_classes = [IsAuthenticated]
http_method_names = ('put',)
def put(self, request, *args, **kwargs):
""" junior list"""
try:
junior_instance = Junior.objects.filter(auth=self.request.user).last()
article = self.request.data.get('article_id')
article_card = self.request.data.get('article_card')
JuniorArticleCard.objects.filter(junior=junior_instance,
article__id=article,
article_card__id=article_card).update(is_read=True)
return custom_response(SUCCESS_CODE['3043'], response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
class CreateArticleCardAPIView(viewsets.ModelViewSet):
"""Start article"""
permission_classes = [IsAuthenticated]
http_method_names = ('post',)
def create(self, request, *args, **kwargs):
""" junior list"""
try:
junior_instance = Junior.objects.filter(auth=self.request.user).last()
article_id = request.data.get('article_id')
article_data = Article.objects.filter(id=article_id).last()
if article_data:
article_cards = ArticleCard.objects.filter(article=article_id)
for article_card in article_cards:
if not JuniorArticleCard.objects.filter(junior=junior_instance,
article=article_data,
article_card=article_card):
JuniorArticleCard.objects.create(junior=junior_instance,
article=article_data,
article_card=article_card)
return custom_response(None, response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)