From 74c3b996e1c51206f712d4aa63c4b3d7f4ce372f Mon Sep 17 00:00:00 2001 From: lordgrim18 Date: Sun, 22 Oct 2023 19:00:54 +0530 Subject: [PATCH 1/9] feat(karma_voucher): add create method --- .../karma_voucher/karma_voucher_serializer.py | 74 ++++++++++++++++++- .../karma_voucher/karma_voucher_view.py | 10 ++- api/dashboard/karma_voucher/urls.py | 2 + 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/api/dashboard/karma_voucher/karma_voucher_serializer.py b/api/dashboard/karma_voucher/karma_voucher_serializer.py index f82dcc04..ceb9137b 100644 --- a/api/dashboard/karma_voucher/karma_voucher_serializer.py +++ b/api/dashboard/karma_voucher/karma_voucher_serializer.py @@ -1,7 +1,12 @@ +import uuid from rest_framework import serializers -from db.task import VoucherLog +from db.task import VoucherLog, TaskList +from db.user import User +from utils.permission import JWTUtils +from utils.utils import DateTimeUtils +from utils.karma_voucher import generate_ordered_id class VoucherLogCSVSerializer(serializers.ModelSerializer): user_id = serializers.CharField(required=True, allow_null=False) @@ -39,3 +44,70 @@ class Meta: "updated_at", "muid" ] + +class VoucherLogCreateSerializer(serializers.ModelSerializer): + user = serializers.CharField(required=True, error_messages={ + 'required': 'user field must not be left blank.' + }) + task = serializers.CharField(required=True, error_messages={ + 'required': 'task field must not be left blank.' + }) + karma = serializers.IntegerField(required=True, error_messages={ + 'required': 'karma field must not be left blank.' + }) + month = serializers.CharField(required=True, error_messages={ + 'required': 'month field must not be left blank.' + }) + week = serializers.CharField(required=True, error_messages={ + 'required': 'week field must not be left blank.' + }) + claimed = serializers.BooleanField(default=False) + + class Meta: + model = VoucherLog + fields = [ + "user", + "task", + "karma", + "month", + "week", + "claimed", + ] + + def create(self, validated_data): + user_id = JWTUtils.fetch_user_id(self.context.get('request')) + validated_data['user_id'] = validated_data.pop('user') + validated_data['task_id'] = validated_data.pop('task') + validated_data['id'] = uuid.uuid4() + + existing_codes = set(VoucherLog.objects.values_list('code', flat=True)) + count = 1 + while generate_ordered_id(count) in existing_codes: + count += 1 + + validated_data['code'] = generate_ordered_id(count) + validated_data['updated_by_id'] = user_id + validated_data['updated_at'] = DateTimeUtils.get_current_utc_time() + validated_data['created_by_id'] = user_id + validated_data['created_at'] = DateTimeUtils.get_current_utc_time() + return VoucherLog.objects.create(**validated_data) + + def validate_user(self, value): + if not User.objects.filter(id=value).exists(): + raise serializers.ValidationError("Enter a valid user") + return value + + def validate_task(self, value): + if not TaskList.objects.filter(id=value).exists(): + raise serializers.ValidationError("Enter a valid task") + return value + + def validate_karma(self, value): + if value <= 0: + raise serializers.ValidationError("Enter a valid karma") + return value + + def validate_week(self, value): + if len(value) != 2: + raise serializers.ValidationError("Week must have exactly two characters.") + return value \ No newline at end of file diff --git a/api/dashboard/karma_voucher/karma_voucher_view.py b/api/dashboard/karma_voucher/karma_voucher_view.py index eb303075..01a0eb51 100644 --- a/api/dashboard/karma_voucher/karma_voucher_view.py +++ b/api/dashboard/karma_voucher/karma_voucher_view.py @@ -14,7 +14,7 @@ from utils.types import RoleType from utils.utils import DateTimeUtils from utils.utils import ImportCSV, CommonUtils -from .karma_voucher_serializer import VoucherLogCSVSerializer, VoucherLogSerializer +from .karma_voucher_serializer import VoucherLogCSVSerializer, VoucherLogSerializer, VoucherLogCreateSerializer class ImportVoucherLogAPI(APIView): @@ -203,6 +203,14 @@ def get(self, request): voucher_serializer = VoucherLogSerializer(paginated_queryset.get('queryset'), many=True).data return CustomResponse().paginated_response(data=voucher_serializer, pagination=paginated_queryset.get('pagination')) + + def post(self, request): + serializer = VoucherLogCreateSerializer(data=request.data, context={'request': request}) + if serializer.is_valid(): + serializer.save() + return CustomResponse(general_message='Voucher created successfully', + response=serializer.data).get_success_response() + return CustomResponse(message=serializer.errors).get_failure_response() class ExportVoucherLogAPI(APIView): diff --git a/api/dashboard/karma_voucher/urls.py b/api/dashboard/karma_voucher/urls.py index d022aa46..1acceaf2 100644 --- a/api/dashboard/karma_voucher/urls.py +++ b/api/dashboard/karma_voucher/urls.py @@ -6,4 +6,6 @@ path('', karma_voucher_view.VoucherLogAPI.as_view()), path('import/', karma_voucher_view.ImportVoucherLogAPI.as_view()), path('export/', karma_voucher_view.ExportVoucherLogAPI.as_view()), + + path('create/', karma_voucher_view.VoucherLogAPI.as_view()), ] \ No newline at end of file From 9c655698bdccfd50df435f3c7f086e14ba29c471 Mon Sep 17 00:00:00 2001 From: lordgrim18 Date: Sun, 22 Oct 2023 19:20:22 +0530 Subject: [PATCH 2/9] fix(karma_voucher): create method --- api/dashboard/karma_voucher/karma_voucher_serializer.py | 3 +-- api/dashboard/karma_voucher/karma_voucher_view.py | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/dashboard/karma_voucher/karma_voucher_serializer.py b/api/dashboard/karma_voucher/karma_voucher_serializer.py index ceb9137b..b38bbeb0 100644 --- a/api/dashboard/karma_voucher/karma_voucher_serializer.py +++ b/api/dashboard/karma_voucher/karma_voucher_serializer.py @@ -61,7 +61,6 @@ class VoucherLogCreateSerializer(serializers.ModelSerializer): week = serializers.CharField(required=True, error_messages={ 'required': 'week field must not be left blank.' }) - claimed = serializers.BooleanField(default=False) class Meta: model = VoucherLog @@ -71,7 +70,6 @@ class Meta: "karma", "month", "week", - "claimed", ] def create(self, validated_data): @@ -86,6 +84,7 @@ def create(self, validated_data): count += 1 validated_data['code'] = generate_ordered_id(count) + validated_data['claimed'] = False validated_data['updated_by_id'] = user_id validated_data['updated_at'] = DateTimeUtils.get_current_utc_time() validated_data['created_by_id'] = user_id diff --git a/api/dashboard/karma_voucher/karma_voucher_view.py b/api/dashboard/karma_voucher/karma_voucher_view.py index 01a0eb51..b6a00eb2 100644 --- a/api/dashboard/karma_voucher/karma_voucher_view.py +++ b/api/dashboard/karma_voucher/karma_voucher_view.py @@ -204,6 +204,7 @@ def get(self, request): return CustomResponse().paginated_response(data=voucher_serializer, pagination=paginated_queryset.get('pagination')) + @role_required([RoleType.ADMIN.value, RoleType.FELLOW.value, RoleType.ASSOCIATE.value]) def post(self, request): serializer = VoucherLogCreateSerializer(data=request.data, context={'request': request}) if serializer.is_valid(): From 6b49e4ad00022d70c9443c5b07df814ace6852f3 Mon Sep 17 00:00:00 2001 From: Muhammed Zafar Date: Sun, 22 Oct 2023 21:03:36 +0530 Subject: [PATCH 3/9] [PATCH] Minor patch in middlewares (#1397) * [FEAT] Configure CustomException Error handling * [PATCH] Log non-JSON data (#1388) * [PATCH] Minor patch in middlewares --------- Co-authored-by: Adnan Kattekaden <71538497+adnankattekaden@users.noreply.github.com> Co-authored-by: Aashish Vinu --- mulearnbackend/middlewares.py | 26 +++++++++++++++----------- mulearnbackend/settings.py | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/mulearnbackend/middlewares.py b/mulearnbackend/middlewares.py index 987fb866..5655b982 100644 --- a/mulearnbackend/middlewares.py +++ b/mulearnbackend/middlewares.py @@ -1,8 +1,9 @@ +from contextlib import suppress import hmac import json +import json import logging import traceback -from contextlib import suppress import decouple from django.conf import settings @@ -95,7 +96,7 @@ def __call__(self, request): def log_exception(self, request, exception): """ - Log the exception and prints the information in CLI if DEBUG is True. + Log the exception and prints the information in CLI. Args: request: The request object. @@ -109,24 +110,27 @@ def log_exception(self, request, exception): ) logger.error(error_message) - if settings.DEBUG: - print(error_message) + print(error_message) - data = request.body.decode('utf-8')) if hasattr(request, 'body') else 'No Data' + body = request.body.decode("utf-8") if hasattr(request, "body") else "No body" + auth = request.auth if hasattr(request, "auth") else "No Auth data" + + with suppress(json.JSONDecodeError): + body = json.loads(body) + body = json.dumps(body, indent=4) with suppress(json.JSONDecodeError): - data = json.loads(data) + auth = json.dumps(auth, indent=4) request_info = ( f"Request Info: METHOD: {request.method}; \n" - f"\tPATH: {request.path}; \n" - f"\tDATA: {data}\n" + f"PATH: {request.path}; \n" + f"AUTH: \n{auth} \n" + f"BODY: \n{body}\n" ) logger.error(request_info) - # Print to terminal if DEBUG is True - if settings.DEBUG: - print(request_info) + print(request_info) def process_exception(self, request, exception): """ diff --git a/mulearnbackend/settings.py b/mulearnbackend/settings.py index bcf502a0..daa1faca 100644 --- a/mulearnbackend/settings.py +++ b/mulearnbackend/settings.py @@ -57,7 +57,7 @@ "debug_toolbar.middleware.DebugToolbarMiddleware", "django.middleware.common.CommonMiddleware", "corsheaders.middleware.CorsMiddleware", - # "mulearnbackend.middlewares.UniversalErrorHandlerMiddleware", + "mulearnbackend.middlewares.UniversalErrorHandlerMiddleware", ] ROOT_URLCONF = "mulearnbackend.urls" From 0298874cd39f0e22f565fc27467249adb06d4ea0 Mon Sep 17 00:00:00 2001 From: lordgrim18 Date: Sun, 22 Oct 2023 21:54:25 +0530 Subject: [PATCH 4/9] feat(karma_voucher): add update and delete method --- .../karma_voucher/karma_voucher_serializer.py | 36 +++++++++++++++++-- .../karma_voucher/karma_voucher_view.py | 25 +++++++++++-- api/dashboard/karma_voucher/urls.py | 2 ++ 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/api/dashboard/karma_voucher/karma_voucher_serializer.py b/api/dashboard/karma_voucher/karma_voucher_serializer.py index b38bbeb0..7e929dc2 100644 --- a/api/dashboard/karma_voucher/karma_voucher_serializer.py +++ b/api/dashboard/karma_voucher/karma_voucher_serializer.py @@ -1,9 +1,7 @@ import uuid from rest_framework import serializers - from db.task import VoucherLog, TaskList from db.user import User - from utils.permission import JWTUtils from utils.utils import DateTimeUtils from utils.karma_voucher import generate_ordered_id @@ -109,4 +107,36 @@ def validate_karma(self, value): def validate_week(self, value): if len(value) != 2: raise serializers.ValidationError("Week must have exactly two characters.") - return value \ No newline at end of file + return value + +class VoucherLogUpdateSerializer(serializers.ModelSerializer): + user = serializers.CharField(required=False) + task = serializers.CharField(required=False) + karma = serializers.IntegerField(required=False) + month = serializers.CharField(required=False) + week = serializers.CharField(required=False) + + class Meta: + model = VoucherLog + fields = [ + "user", + "task", + "karma", + "month", + "week", + ] + + def update(self, instance, validated_data): + instance.user_id = validated_data.get('user', instance.user) + instance.task_id = validated_data.get('task', instance.task) + instance.karma = validated_data.get('karma', instance.karma) + instance.month = validated_data.get('month', instance.month) + instance.week = validated_data.get('week', instance.week) + + instance.updated_by_id = self.context.get('user_id') + instance.updated_at = DateTimeUtils.get_current_utc_time() + instance.save() + return instance + + def destroy(self, obj): + obj.delete() \ No newline at end of file diff --git a/api/dashboard/karma_voucher/karma_voucher_view.py b/api/dashboard/karma_voucher/karma_voucher_view.py index b6a00eb2..2e5a7d74 100644 --- a/api/dashboard/karma_voucher/karma_voucher_view.py +++ b/api/dashboard/karma_voucher/karma_voucher_view.py @@ -14,7 +14,7 @@ from utils.types import RoleType from utils.utils import DateTimeUtils from utils.utils import ImportCSV, CommonUtils -from .karma_voucher_serializer import VoucherLogCSVSerializer, VoucherLogSerializer, VoucherLogCreateSerializer +from .karma_voucher_serializer import VoucherLogCSVSerializer, VoucherLogSerializer, VoucherLogCreateSerializer, VoucherLogUpdateSerializer class ImportVoucherLogAPI(APIView): @@ -212,7 +212,28 @@ def post(self, request): return CustomResponse(general_message='Voucher created successfully', response=serializer.data).get_success_response() return CustomResponse(message=serializer.errors).get_failure_response() - + + @role_required([RoleType.ADMIN.value, RoleType.FELLOW.value, RoleType.ASSOCIATE.value]) + def patch(self, request, voucher_id): + user_id = JWTUtils.fetch_user_id(request) + context = {'user_id': user_id} + voucher = VoucherLog.objects.filter(id=voucher_id).first() + serializer = VoucherLogUpdateSerializer(voucher, data=request.data, context=context) + if serializer.is_valid(): + serializer.save() + return CustomResponse(general_message='Voucher updated successfully').get_success_response() + return CustomResponse(message=serializer.errors).get_failure_response() + + @role_required([RoleType.ADMIN.value, RoleType.FELLOW.value, RoleType.ASSOCIATE.value]) + def delete(self, request, voucher_id): + if voucher_log := VoucherLog.objects.filter(id=voucher_id).first(): + VoucherLogUpdateSerializer().destroy(voucher_log) + return CustomResponse( + general_message=f'Voucher successfully deleted' + ).get_success_response() + return CustomResponse( + general_message=f'Invalid Voucher' + ).get_failure_response() class ExportVoucherLogAPI(APIView): authentication_classes = [CustomizePermission] diff --git a/api/dashboard/karma_voucher/urls.py b/api/dashboard/karma_voucher/urls.py index 1acceaf2..43356fca 100644 --- a/api/dashboard/karma_voucher/urls.py +++ b/api/dashboard/karma_voucher/urls.py @@ -8,4 +8,6 @@ path('export/', karma_voucher_view.ExportVoucherLogAPI.as_view()), path('create/', karma_voucher_view.VoucherLogAPI.as_view()), + path('update//', karma_voucher_view.VoucherLogAPI.as_view()), + path('delete//', karma_voucher_view.VoucherLogAPI.as_view()), ] \ No newline at end of file From e2d401bbdf99a59f657cd46cb97760d39d0faa38 Mon Sep 17 00:00:00 2001 From: Muhammed Zafar Date: Sun, 22 Oct 2023 22:36:23 +0530 Subject: [PATCH 5/9] [PATCH] Minor patch in onboarding (#1400) --- .../organisation/organisation_views.py | 316 +++++++----------- api/dashboard/organisation/serializers.py | 146 +++----- api/dashboard/organisation/urls.py | 2 +- api/register/register_helper.py | 18 + api/register/register_views.py | 190 +++-------- api/register/serializers.py | 21 +- 6 files changed, 238 insertions(+), 455 deletions(-) diff --git a/api/dashboard/organisation/organisation_views.py b/api/dashboard/organisation/organisation_views.py index bda40e1c..9b78ceab 100644 --- a/api/dashboard/organisation/organisation_views.py +++ b/api/dashboard/organisation/organisation_views.py @@ -1,26 +1,23 @@ -from django.db.models import Sum, Q, F, Window, Case, When, Count -from django.db.models.functions import Rank +from django.db.models import F, Prefetch, Sum from rest_framework.views import APIView from db.organization import ( - Organization, - OrgAffiliation, Department, + OrgAffiliation, + Organization, + UserOrganizationLink, ) -from utils.permission import CustomizePermission, JWTUtils -from utils.permission import role_required +from utils.permission import CustomizePermission, JWTUtils, role_required from utils.response import CustomResponse -from utils.types import RoleType, OrganizationType -from utils.types import WebHookCategory, WebHookActions -from utils.utils import CommonUtils -from utils.utils import DiscordWebhooks +from utils.types import OrganizationType, RoleType, WebHookActions, WebHookCategory +from utils.utils import CommonUtils, DiscordWebhooks + from .serializers import ( + AffiliationCreateUpdateSerializer, AffiliationSerializer, - InstitutionCsvSerializer, DepartmentSerializer, - InstitutionSerializer, InstitutionCreateUpdateSerializer, - AffiliationCreateUpdateSerializer, + InstitutionSerializer, ) @@ -29,14 +26,10 @@ class InstitutionPostUpdateDeleteAPI(APIView): @role_required([RoleType.ADMIN.value]) def post(self, request): - user_id = JWTUtils.fetch_user_id(request) serializer = InstitutionCreateUpdateSerializer( - data=request.data, - context={ - "user_id": user_id - } + data=request.data, context={"user_id": user_id} ) if serializer.is_valid(): @@ -53,18 +46,13 @@ def post(self, request): general_message="Organisation added successfully" ).get_success_response() - return CustomResponse( - general_message=serializer.errors - ).get_failure_response() + return CustomResponse(general_message=serializer.errors).get_failure_response() @role_required([RoleType.ADMIN.value]) def put(self, request, org_code): - user_id = JWTUtils.fetch_user_id(request) - organization = Organization.objects.filter( - code=org_code - ).first() + organization = Organization.objects.filter(code=org_code).first() if organization is None: return CustomResponse( @@ -75,18 +63,16 @@ def put(self, request, org_code): old_type = organization.org_type serializer = InstitutionCreateUpdateSerializer( - organization, - data=request.data, - context={ - "user_id": user_id - } + organization, data=request.data, context={"user_id": user_id} ) if serializer.is_valid(): serializer.save() - if (request.data.get("title") != old_title and - old_type == OrganizationType.COMMUNITY.value): + if ( + request.data.get("title") != old_title + and old_type == OrganizationType.COMMUNITY.value + ): DiscordWebhooks.general_updates( WebHookCategory.COMMUNITY.value, WebHookActions.EDIT.value, @@ -94,37 +80,34 @@ def put(self, request, org_code): old_title, ) - if (request.data.get("orgType") != OrganizationType.COMMUNITY.value and - old_type == OrganizationType.COMMUNITY.value): + if ( + request.data.get("orgType") != OrganizationType.COMMUNITY.value + and old_type == OrganizationType.COMMUNITY.value + ): DiscordWebhooks.general_updates( WebHookCategory.COMMUNITY.value, WebHookActions.DELETE.value, old_title, ) - if (old_type != OrganizationType.COMMUNITY.value and - request.data.get("orgType") == OrganizationType.COMMUNITY.value): + if ( + old_type != OrganizationType.COMMUNITY.value + and request.data.get("orgType") == OrganizationType.COMMUNITY.value + ): title = request.data.get("title") or old_title DiscordWebhooks.general_updates( - WebHookCategory.COMMUNITY.value, - WebHookActions.CREATE.value, - title + WebHookCategory.COMMUNITY.value, WebHookActions.CREATE.value, title ) return CustomResponse( general_message="Organization edited successfully" ).get_success_response() - return CustomResponse( - message=serializer.errors - ).get_failure_response() + return CustomResponse(message=serializer.errors).get_failure_response() @role_required([RoleType.ADMIN.value]) def delete(self, request, org_code): - - if not ( - organisation := Organization.objects.filter(code=org_code).first() - ): + if not (organisation := Organization.objects.filter(code=org_code).first()): return CustomResponse( general_message=f"Org with code '{org_code}', does not exist" ).get_failure_response() @@ -146,8 +129,23 @@ def delete(self, request, org_code): class InstitutionAPI(APIView): def get(self, request, org_type): - organizations = Organization.objects.filter( - org_type=org_type + organizations = ( + Organization.objects.filter(org_type=org_type) + .select_related( + "affiliation", + "district__zone__state__country", + "district__zone__state", + "district__zone", + "district", + ) + .prefetch_related( + Prefetch( + "user_organization_link_org", + queryset=UserOrganizationLink.objects.filter( + verified=True + ).select_related("user"), + ) + ) ) paginated_queryset = CommonUtils.get_paginated_queryset( @@ -160,7 +158,7 @@ def get(self, request, org_type): "district__name", "district__zone__name", "district__zone__state__name", - "district__zone__state__country__name" + "district__zone__state__country__name", ], { "title": "title", @@ -169,7 +167,7 @@ def get(self, request, org_type): "district": "district__name", "zone": "district__zone__name", "state": "district__zone__state__name", - "country": "district__zone__state__country__name" + "country": "district__zone__state__country__name", }, ) @@ -185,94 +183,85 @@ def get(self, request, org_type): ).get_success_response() -class InstitutionCsvAPI(APIView): +class InstitutionCSVAPI(APIView): authentication_classes = [CustomizePermission] @role_required([RoleType.ADMIN.value]) def get(self, request, org_type): - organization = Organization.objects.filter( - org_type=org_type - ).prefetch_related( - "affiliation", - "district__zone__state__country" + organizations = ( + Organization.objects.filter(org_type=org_type) + .select_related( + "affiliation", + "district__zone__state__country", + "district__zone__state", + "district__zone", + "district", + ) + .prefetch_related( + Prefetch( + "user_organization_link_org", + queryset=UserOrganizationLink.objects.filter( + verified=True + ).select_related("user"), + ) + ) ) - serializer = InstitutionCsvSerializer( - organization, - many=True - ).data + serializer = InstitutionSerializer(organizations, many=True).data - return CommonUtils.generate_csv( - serializer, - f"{org_type} data" - ) + return CommonUtils.generate_csv(serializer, f"{org_type} data") class InstitutionDetailsAPI(APIView): - @role_required([RoleType.ADMIN.value, ]) + @role_required( + [ + RoleType.ADMIN.value, + ] + ) def get(self, request, org_code): - - organization = Organization.objects.filter( - code=org_code - ).values( - "id", - "title", - "code", - affiliation_uuid=F("affiliation__id"), - affiliation_name=F("affiliation__title"), - district_uuid=F("district__id"), - district_name=F("district__name"), - zone_uuid=F("district__zone__id"), - zone_name=F("district__zone__name"), - state_uuid=F("district__zone__state__id"), - state_name=F("district__zone__state__name"), - country_uuid=F("district__zone__state__country__id"), - country_name=F("district__zone__state__country__name"), - ).annotate( - karma=Sum( - 'user_organization_link_org__user__wallet_user__karma' - )).order_by( - '-karma' + organization = ( + Organization.objects.filter(code=org_code) + .values( + "id", + "title", + "code", + affiliation_uuid=F("affiliation__id"), + affiliation_name=F("affiliation__title"), + district_uuid=F("district__id"), + district_name=F("district__name"), + zone_uuid=F("district__zone__id"), + zone_name=F("district__zone__name"), + state_uuid=F("district__zone__state__id"), + state_name=F("district__zone__state__name"), + country_uuid=F("district__zone__state__country__id"), + country_name=F("district__zone__state__country__name"), ) + .annotate(karma=Sum("user_organization_link_org__user__wallet_user__karma")) + .order_by("-karma") + ) - return CustomResponse( - response=organization - ).get_success_response() + return CustomResponse(response=organization).get_success_response() class GetInstitutionsAPI(APIView): def get(self, request, org_type, district_id=None): - if district_id: organisations = Organization.objects.filter( - org_type=org_type, - district_id=district_id + org_type=org_type, district_id=district_id ) else: - organisations = Organization.objects.filter( - org_type=org_type - ) + organisations = Organization.objects.filter(org_type=org_type) paginated_organisations = CommonUtils.get_paginated_queryset( - organisations, - request, - [ - "title", - "code" - ] + organisations, request, ["title", "code"] ) - organisation_serializer = InstitutionCsvSerializer( - paginated_organisations.get( - "queryset" - ), - many=True + organisation_serializer = InstitutionSerializer( + paginated_organisations.get("queryset"), many=True ) return CustomResponse().paginated_response( data=organisation_serializer.data, - pagination=paginated_organisations.get( - "pagination" - ), + pagination=paginated_organisations.get("pagination"), ) @@ -280,37 +269,28 @@ class AffiliationGetPostUpdateDeleteAPI(APIView): authentication_classes = [CustomizePermission] def get(self, request): - affiliation = OrgAffiliation.objects.all() paginated_queryset = CommonUtils.get_paginated_queryset( - affiliation, - request, - [ - "id", - "title" - ]) + affiliation, request, ["id", "title"] + ) serializer = AffiliationSerializer( - paginated_queryset.get("queryset"), - many=True + paginated_queryset.get("queryset"), many=True ) return CustomResponse().paginated_response( - data=serializer.data, - pagination=paginated_queryset.get( - "pagination" - )) + data=serializer.data, pagination=paginated_queryset.get("pagination") + ) @role_required([RoleType.ADMIN.value]) def post(self, request): - user_id = JWTUtils.fetch_user_id(request) serializer = AffiliationCreateUpdateSerializer( data=request.data, context={ "user_id": user_id, - } + }, ) if serializer.is_valid(): @@ -320,18 +300,13 @@ def post(self, request): general_message=f"{request.data.get('title')} added successfully" ).get_success_response() - return CustomResponse( - general_message=serializer.errors - ).get_failure_response() + return CustomResponse(general_message=serializer.errors).get_failure_response() @role_required([RoleType.ADMIN.value]) def put(self, request, affiliation_id): - user_id = JWTUtils.fetch_user_id(request) - affiliation = OrgAffiliation.objects.filter( - id=affiliation_id - ).first() + affiliation = OrgAffiliation.objects.filter(id=affiliation_id).first() if affiliation is None: return CustomResponse( @@ -339,11 +314,7 @@ def put(self, request, affiliation_id): ).get_failure_response() serializer = AffiliationCreateUpdateSerializer( - affiliation, - data=request.data, - context={ - "user_id": user_id - } + affiliation, data=request.data, context={"user_id": user_id} ) if serializer.is_valid(): @@ -353,16 +324,11 @@ def put(self, request, affiliation_id): general_message=f"{affiliation.title} Edited Successfully" ).get_success_response() - return CustomResponse( - message=serializer.errors - ).get_failure_response() + return CustomResponse(message=serializer.errors).get_failure_response() @role_required([RoleType.ADMIN.value]) def delete(self, request, affiliation_id): - - affiliation = OrgAffiliation.objects.filter( - id=affiliation_id - ).first() + affiliation = OrgAffiliation.objects.filter(id=affiliation_id).first() if affiliation is None: return CustomResponse( @@ -381,43 +347,26 @@ class DepartmentAPI(APIView): @role_required([RoleType.ADMIN.value]) def get(self, request, dept_id=None): - if dept_id: - departments = Department.objects.filter( - id=dept_id - ) + departments = Department.objects.filter(id=dept_id) else: departments = Department.objects.all() paginated_queryset = CommonUtils.get_paginated_queryset( - departments, - request, - [ - "title" - ], - { - "title": "title" - }) - - serializer = DepartmentSerializer( - paginated_queryset.get( - "queryset" - ), many=True + departments, request, ["title"], {"title": "title"} ) + serializer = DepartmentSerializer(paginated_queryset.get("queryset"), many=True) + return CustomResponse().paginated_response( - data=serializer.data, - pagination=paginated_queryset.get( - "pagination" - )) + data=serializer.data, pagination=paginated_queryset.get("pagination") + ) @role_required([RoleType.ADMIN.value]) def post(self, request): serializer = DepartmentSerializer( - data=request.data, - context={ - "request": request - }) + data=request.data, context={"request": request} + ) if serializer.is_valid(): serializer.save() @@ -426,43 +375,30 @@ def post(self, request): general_message=f"{request.data.get('title')} created successfully" ).get_success_response() - return CustomResponse( - response=serializer.errors - ).get_failure_response() + return CustomResponse(response=serializer.errors).get_failure_response() @role_required([RoleType.ADMIN.value]) def put(self, request, department_id): - - department = Department.objects.get( - id=department_id - ) + department = Department.objects.get(id=department_id) serializer = DepartmentSerializer( - department, - data=request.data, - context={ - "request": request - }) + department, data=request.data, context={"request": request} + ) if serializer.is_valid(): serializer.save() return CustomResponse( - general_message=f'{department.title} updated successfully' + general_message=f"{department.title} updated successfully" ).get_success_response() - return CustomResponse( - response=serializer.errors - ).get_failure_response() + return CustomResponse(response=serializer.errors).get_failure_response() @role_required([RoleType.ADMIN.value]) def delete(self, request, department_id): - - department = Department.objects.get( - id=department_id - ) + department = Department.objects.get(id=department_id) department.delete() return CustomResponse( - general_message=f'{department.title} deleted successfully' + general_message=f"{department.title} deleted successfully" ).get_success_response() diff --git a/api/dashboard/organisation/serializers.py b/api/dashboard/organisation/serializers.py index a2e30279..42878868 100644 --- a/api/dashboard/organisation/serializers.py +++ b/api/dashboard/organisation/serializers.py @@ -8,46 +8,19 @@ from rest_framework import serializers -from db.organization import Organization, District, Zone, State, OrgAffiliation, Department +from db.organization import ( + Organization, + District, + Zone, + State, + OrgAffiliation, + Department, +) class InstitutionSerializer(serializers.ModelSerializer): - - affiliation = serializers.ReadOnlyField(source="affiliation.title") - district = serializers.ReadOnlyField(source="district.name") - zone = serializers.ReadOnlyField(source="district.zone.name") - state = serializers.ReadOnlyField(source="district.zone.state.name") - country = serializers.ReadOnlyField(source="district.zone.state.country.name") - user_count = serializers.SerializerMethodField() - - class Meta: - model = Organization - fields = [ - "id", - "title", - "code", - "affiliation", - "district", - "zone", - "state", - "country", - "user_count" - ] - - def get_user_count(self, obj): - return obj.user_organization_link_org.annotate( - user_count=Count( - 'user' - ) - ).count() - - -class InstitutionCsvSerializer(serializers.ModelSerializer): - affiliation = serializers.SlugRelatedField( - many=False, - read_only=True, - slug_field="title" + many=False, read_only=True, slug_field="title" ) district = serializers.ReadOnlyField(source="district.name") @@ -68,19 +41,17 @@ class Meta: "zone", "state", "country", - "user_count" + "user_count", ] def get_user_count(self, obj): - return obj.user_organization_link_org.annotate( - user_count=Count( - 'user' - ) - ).count() + return len({link.user for link in obj.user_organization_link_org.all()}) class StateSerializer(serializers.ModelSerializer): - country = serializers.SlugRelatedField(many=False, read_only=True, slug_field="name") + country = serializers.SlugRelatedField( + many=False, read_only=True, slug_field="name" + ) class Meta: model = State @@ -104,99 +75,74 @@ class Meta: class InstitutionCreateUpdateSerializer(serializers.ModelSerializer): - class Meta: model = Organization - fields = [ - "title", - "code", - "org_type", - "affiliation", - "district" - ] + fields = ["title", "code", "org_type", "affiliation", "district"] def create(self, validated_data): - user_id = self.context.get('user_id') - validated_data['id'] = str(uuid.uuid4()) - validated_data['created_by_id'] = user_id - validated_data['updated_by_id'] = user_id + user_id = self.context.get("user_id") + validated_data["id"] = str(uuid.uuid4()) + validated_data["created_by_id"] = user_id + validated_data["updated_by_id"] = user_id return Organization.objects.create(**validated_data) def update(self, instance, validated_data): - user_id = self.context.get('user_id') - instance.title = validated_data.get('title', instance.title) - instance.code = validated_data.get('code', instance.code) - instance.affiliation = validated_data.get('affiliation', instance.affiliation) + user_id = self.context.get("user_id") + instance.title = validated_data.get("title", instance.title) + instance.code = validated_data.get("code", instance.code) + instance.affiliation = validated_data.get("affiliation", instance.affiliation) instance.updated_by_id = user_id instance.save() return instance def validate_org_type(self, organization): if organization == OrganizationType.COLLEGE.value: - affiliation = self.initial_data.get('affiliation') - org_affiliation = OrgAffiliation.objects.filter( - id=affiliation - ).first() + affiliation = self.initial_data.get("affiliation") + org_affiliation = OrgAffiliation.objects.filter(id=affiliation).first() if org_affiliation is None: - raise serializers.ValidationError( - "Invalid organization affiliation" - ) + raise serializers.ValidationError("Invalid organization affiliation") return organization def validate_affiliation(self, affiliation_id): - if self.initial_data.get('org_type') != OrganizationType.COLLEGE.value: + if self.initial_data.get("org_type") != OrganizationType.COLLEGE.value: return None return affiliation_id class AffiliationSerializer(serializers.ModelSerializer): - - label = serializers.ReadOnlyField(source='title') - value = serializers.ReadOnlyField(source='id') + label = serializers.ReadOnlyField(source="title") + value = serializers.ReadOnlyField(source="id") class Meta: model = OrgAffiliation - fields = [ - "value", - "label" - ] + fields = ["value", "label"] class AffiliationCreateUpdateSerializer(serializers.ModelSerializer): - class Meta: model = OrgAffiliation - fields = [ - "title" - ] + fields = ["title"] def create(self, validated_data): - user_id = self.context.get('user_id') - validated_data['created_by_id'] = user_id - validated_data['updated_by_id'] = user_id + user_id = self.context.get("user_id") + validated_data["created_by_id"] = user_id + validated_data["updated_by_id"] = user_id return OrgAffiliation.objects.create(**validated_data) def update(self, instance, validated_data): - user_id = self.context.get('user_id') - instance.title = validated_data.get('title', instance.title) + user_id = self.context.get("user_id") + instance.title = validated_data.get("title", instance.title) instance.updated_by_id = user_id instance.save() return instance def validate_title(self, title): - - org_affiliation = OrgAffiliation.objects.filter( - title=title - ).first() - - if org_affiliation: - raise serializers.ValidationError( - "Affiliation already exist" - ) + if OrgAffiliation.objects.filter(title=title).first(): + raise serializers.ValidationError("Affiliation already exist") return title @@ -206,22 +152,20 @@ class DepartmentSerializer(serializers.ModelSerializer): class Meta: model = Department - fields = ["id", - "title"] + fields = ["id", "title"] def create(self, validated_data): - user_id = JWTUtils.fetch_user_id(self.context.get('request')) - validated_data['title'] = self.data.get('title') - validated_data['updated_by_id'] = user_id - validated_data['created_by_id'] = user_id + user_id = JWTUtils.fetch_user_id(self.context.get("request")) + validated_data["title"] = self.data.get("title") + validated_data["updated_by_id"] = user_id + validated_data["created_by_id"] = user_id return Department.objects.create(**validated_data) def update(self, instance, validated_data): - updated_title = validated_data.get('title') + updated_title = validated_data.get("title") instance.title = updated_title - user_id = JWTUtils.fetch_user_id(self.context.get('request')) + user_id = JWTUtils.fetch_user_id(self.context.get("request")) instance.updated_by_id = user_id instance.save() return instance - diff --git a/api/dashboard/organisation/urls.py b/api/dashboard/organisation/urls.py index 209ba000..0e9c83b6 100644 --- a/api/dashboard/organisation/urls.py +++ b/api/dashboard/organisation/urls.py @@ -8,7 +8,7 @@ path('institutes/edit//', organisation_views.InstitutionPostUpdateDeleteAPI.as_view()), path('institutes/delete//', organisation_views.InstitutionPostUpdateDeleteAPI.as_view()), path('institutes//', organisation_views.InstitutionAPI.as_view()), - path('institutes//csv/', organisation_views.InstitutionCsvAPI.as_view()), + path('institutes//csv/', organisation_views.InstitutionCSVAPI.as_view()), path('institutes/info//', organisation_views.InstitutionDetailsAPI.as_view()), path('institutes/show//', organisation_views.GetInstitutionsAPI.as_view()), path('institutes/show///', organisation_views.GetInstitutionsAPI.as_view()), diff --git a/api/register/register_helper.py b/api/register/register_helper.py index 5ce78229..0c539dc0 100644 --- a/api/register/register_helper.py +++ b/api/register/register_helper.py @@ -1,4 +1,9 @@ +import decouple +import requests + from db.user import User +from utils.exception import CustomException +from utils.response import CustomResponse def get_full_name(first_name, last_name): @@ -15,3 +20,16 @@ def generate_muid(first_name, last_name): muid = f"{full_name}-{counter}@mulearn" return muid + + +def get_auth_token(muid, password): + AUTH_DOMAIN = decouple.config("AUTH_DOMAIN") + response = requests.post( + f"{AUTH_DOMAIN}/api/v1/auth/user-authentication/", + data={"emailOrMuid": muid, "password": password}, + ) + response = response.json() + if response.get("statusCode") != 200: + raise CustomException(response.get("message")) + + return response.get("response") diff --git a/api/register/register_views.py b/api/register/register_views.py index ef69b287..6eb3f266 100644 --- a/api/register/register_views.py +++ b/api/register/register_views.py @@ -11,72 +11,42 @@ from utils.types import OrganizationType from utils.utils import send_template_mail from . import serializers +from .register_helper import get_auth_token class UserRegisterValidateAPI(APIView): def put(self, request): - - serialized_user = serializers.UserSerializer( - data=request.data - ) + serialized_user = serializers.RegisterSerializer(data=request.data) if not serialized_user.is_valid(): return CustomResponse( general_message=serialized_user.errors ).get_failure_response() - return CustomResponse( - response=serialized_user.data - ).get_success_response() + return CustomResponse(response=serialized_user.data).get_success_response() class RoleAPI(APIView): def get(self, request): - role = Role.objects.all().values( - "id", - "title" - ) - - role_serializer_data = serializers.BaseSerializer( - role, - many=True - ).data - - return CustomResponse( - response={"roles": role_serializer_data} - ).get_success_response() + roles = Role.objects.all().values("id", "title") + return CustomResponse(response={"roles": roles}).get_success_response() class CollegesAPI(APIView): def get(self, request): - - college = Organization.objects.filter( + colleges = Organization.objects.filter( org_type=OrganizationType.COLLEGE.value - ).values( - "id", - "title" - ) + ).values("id", "title") - college_serializer_data = serializers.BaseSerializer( - college, - many=True - ).data - - return CustomResponse( - response={"colleges": college_serializer_data} - ).get_success_response() + return CustomResponse(response={"colleges": colleges}).get_success_response() class DepartmentAPI(APIView): def get(self, request): - department_serializer = Department.objects.all().values( - "id", - "title" - ) + department_serializer = Department.objects.all().values("id", "title") department_serializer_data = serializers.BaseSerializer( - department_serializer, - many=True + department_serializer, many=True ).data return CustomResponse( @@ -86,17 +56,12 @@ def get(self, request): class CompanyAPI(APIView): def get(self, request): - company_queryset = Organization.objects.filter( org_type=OrganizationType.COMPANY.value - ).values( - "id", - "title" - ) + ).values("id", "title") company_serializer_data = serializers.BaseSerializer( - company_queryset, - many=True + company_queryset, many=True ).data return CustomResponse( @@ -111,13 +76,9 @@ def post(self, request): user = User.objects.filter(muid=muid).first() if user is None: - return CustomResponse( - general_message="Invalid muid" - ).get_failure_response() + return CustomResponse(general_message="Invalid muid").get_failure_response() - serializer = serializers.LearningCircleUserSerializer( - user - ) + serializer = serializers.LearningCircleUserSerializer(user) id, muid, first_name, last_name, email, phone = serializer.data.values() name = f"{first_name}{last_name or ''}" @@ -148,33 +109,9 @@ def post(self, request): user = create_user.save() password = request.data["user"]["password"] - AUTH_DOMAIN = decouple.config("AUTH_DOMAIN") - response = requests.post( - f"{AUTH_DOMAIN}/api/v1/auth/user-authentication/", - data={ - "emailOrMuid": user.muid, - "password": password - }, - ) - response = response.json() - if response.get("statusCode") != 200: - return CustomResponse( - message=response.get("message") - ).get_failure_response() - - res_data = response.get("response") - access_token = res_data.get("accessToken") - refresh_token = res_data.get("refreshToken") + res_data = get_auth_token(user.muid, password) - response = { - "accessToken": access_token, - "refreshToken": refresh_token, - } - - response_data = serializers.UserDetailSerializer( - user, - many=False - ).data + response_data = serializers.UserDetailSerializer(user, many=False).data send_template_mail( context=response_data, @@ -182,21 +119,16 @@ def post(self, request): address=["user_registration.html"], ) - response["data"] = response_data + res_data["data"] = response_data - return CustomResponse( - response=response - ).get_success_response() + return CustomResponse(response=res_data).get_success_response() class CountryAPI(APIView): def get(self, request): countries = Country.objects.all() - serializer = serializers.CountrySerializer( - countries, - many=True - ) + serializer = serializers.CountrySerializer(countries, many=True) return CustomResponse( response={ @@ -207,13 +139,8 @@ def get(self, request): class StateAPI(APIView): def post(self, request): - state = State.objects.filter( - country_id=request.data.get("country") - ) - serializer = serializers.StateSerializer( - state, - many=True - ) + state = State.objects.filter(country_id=request.data.get("country")) + serializer = serializers.StateSerializer(state, many=True) return CustomResponse( response={ @@ -224,14 +151,9 @@ def post(self, request): class DistrictAPI(APIView): def post(self, request): - district = District.objects.filter( - zone__state_id=request.data.get("state") - ) + district = District.objects.filter(zone__state_id=request.data.get("state")) - serializer = serializers.DistrictSerializer( - district, - many=True - ) + serializer = serializers.DistrictSerializer(district, many=True) return CustomResponse( response={ @@ -249,13 +171,11 @@ def post(self, request): department_queryset = Department.objects.all() college_serializer_data = serializers.OrgSerializer( - org_queryset, - many=True + org_queryset, many=True ).data department_serializer_data = serializers.OrgSerializer( - department_queryset, - many=True + department_queryset, many=True ).data return CustomResponse( @@ -273,8 +193,7 @@ def get(self, request): ) community_serializer_data = serializers.OrgSerializer( - community_queryset, - many=True + community_queryset, many=True ).data return CustomResponse( @@ -287,8 +206,7 @@ def get(self, request): aoi_queryset = InterestGroup.objects.all() aoi_serializer_data = serializers.AreaOfInterestAPISerializer( - aoi_queryset, - many=True + aoi_queryset, many=True ).data return CustomResponse( @@ -300,18 +218,13 @@ class UserEmailVerificationAPI(APIView): def post(self, request): user_email = request.data.get("email") - if user := User.objects.filter( - email=user_email - ).first(): - + if user := User.objects.filter(email=user_email).first(): return CustomResponse( - general_message="This email already exists", - response={"value": True} + general_message="This email already exists", response={"value": True} ).get_success_response() else: return CustomResponse( - general_message="User email not exist", - response={"value": False} + general_message="User email not exist", response={"value": False} ).get_success_response() @@ -324,75 +237,52 @@ def get(self, request): general_message="No data available" ).get_success_response() - country_serializer = serializers.UserCountrySerializer( - country, - many=True - ).data + country_serializer = serializers.UserCountrySerializer(country, many=True).data - return CustomResponse( - response=country_serializer - ).get_success_response() + return CustomResponse(response=country_serializer).get_success_response() class UserStateAPI(APIView): def get(self, request): country_name = request.data.get("country") - country_object = Country.objects.filter( - name=country_name - ).first() + country_object = Country.objects.filter(name=country_name).first() if country_object is None: return CustomResponse( general_message="No country data available" ).get_success_response() - state_object = State.objects.filter( - country_id=country_object - ).all() + state_object = State.objects.filter(country_id=country_object).all() if len(state_object) == 0: return CustomResponse( general_message="No state data available for given country" ).get_success_response() - state_serializer = serializers.UserStateSerializer( - state_object, - many=True - ).data + state_serializer = serializers.UserStateSerializer(state_object, many=True).data - return CustomResponse( - response=state_serializer - ).get_success_response() + return CustomResponse(response=state_serializer).get_success_response() class UserZoneAPI(APIView): def get(self, request): state_name = request.data.get("state") - state_object = State.objects.filter( - name=state_name - ).first() + state_object = State.objects.filter(name=state_name).first() if state_object is None: return CustomResponse( general_message="No state data available" ).get_success_response() - zone_object = Zone.objects.filter( - state_id=state_object - ).all() + zone_object = Zone.objects.filter(state_id=state_object).all() if len(zone_object) == 0: return CustomResponse( general_message="No zone data available for given country" ).get_success_response() - zone_serializer = serializers.UserZoneSerializer( - zone_object, - many=True - ).data + zone_serializer = serializers.UserZoneSerializer(zone_object, many=True).data - return CustomResponse( - response=zone_serializer - ).get_success_response() + return CustomResponse(response=zone_serializer).get_success_response() diff --git a/api/register/serializers.py b/api/register/serializers.py index 3b31feba..ed094826 100644 --- a/api/register/serializers.py +++ b/api/register/serializers.py @@ -77,13 +77,6 @@ class Meta: class UserDetailSerializer(serializers.ModelSerializer): role = serializers.SerializerMethodField() - fullname = serializers.SerializerMethodField() - - def get_fullname(self, obj): - if obj.last_name is None: - return obj.first_name - - return f"{obj.first_name} {obj.last_name}" def get_role(self, obj): role_link = obj.user_role_link_user.filter( @@ -96,8 +89,6 @@ class Meta: fields = [ "id", "muid", - "first_name", - "last_name", "email", "role", "fullname", @@ -148,6 +139,12 @@ class ReferralSerializer(serializers.ModelSerializer): class Meta: model = UserReferralLink fields = ["muid", "user", "invite_code", "is_coin"] + + def to_representation(self, instance): + data = super().to_representation(instance) + if "muid" in data: + data["muid"] = instance.get("muid").muid + return data def validate(self, attrs): if not attrs.get("muid", None) and not attrs.get("invite_code", None): @@ -231,8 +228,6 @@ class UserSerializer(serializers.ModelSerializer): role = serializers.PrimaryKeyRelatedField( queryset=Role.objects.all(), required=False, write_only=True ) - referral = ReferralSerializer(required=False) - integration = IntegrationSerializer(required=False) def create(self, validated_data): role = validated_data.pop("role", None) @@ -274,9 +269,9 @@ class Meta: "email", "mobile", "password", + "dob", + "gender", "role", - "integration", - "referral", ] From 3b4e244c4a4686b9ad4ea6cff3deb2006aec4806 Mon Sep 17 00:00:00 2001 From: Muhammed Zafar Date: Sun, 22 Oct 2023 22:48:27 +0530 Subject: [PATCH 6/9] [FEAT] User registration updates (#1402) --- db/user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/user.py b/db/user.py index 1dfb9277..bbc5fbb5 100644 --- a/db/user.py +++ b/db/user.py @@ -13,7 +13,7 @@ class User(models.Model): email = models.EmailField(unique=True, max_length=200) password = models.CharField(max_length=200, blank=True, null=True) mobile = models.CharField(unique=True, max_length=15) - gender = models.CharField(max_length=10, blank=True, null=True) + gender = models.CharField(max_length=10, blank=True, null=True, choices=["Male", "Female"]) dob = models.DateField(blank=True, null=True) admin = models.BooleanField(default=False) active = models.BooleanField(default=True) From 298bdc80c10a60e76dfaa0e4fbb6f10acb038373 Mon Sep 17 00:00:00 2001 From: anirudh-mk Date: Sun, 22 Oct 2023 23:02:45 +0530 Subject: [PATCH 7/9] feat(interest group api):sortable field added --- api/dashboard/ig/dash_ig_serializer.py | 2 +- api/dashboard/ig/dash_ig_view.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/api/dashboard/ig/dash_ig_serializer.py b/api/dashboard/ig/dash_ig_serializer.py index 9978072e..30429d4e 100644 --- a/api/dashboard/ig/dash_ig_serializer.py +++ b/api/dashboard/ig/dash_ig_serializer.py @@ -26,7 +26,7 @@ class Meta: ] def get_user_ig_link_ig(self, obj): - return len(obj.user_ig_link_ig.all()) + return obj.user_ig_link_ig.all().count() class InterestGroupCreateSerializer(serializers.ModelSerializer): diff --git a/api/dashboard/ig/dash_ig_view.py b/api/dashboard/ig/dash_ig_view.py index 4eb0f94f..bdfa4455 100644 --- a/api/dashboard/ig/dash_ig_view.py +++ b/api/dashboard/ig/dash_ig_view.py @@ -27,7 +27,6 @@ def get(self, request): "user_ig_link_ig" ).all() ) - paginated_queryset = CommonUtils.get_paginated_queryset( ig_queryset, request, @@ -39,7 +38,11 @@ def get(self, request): "updated_by__last_name", ], { - "name": "name" + "name": "name", + "updated_on": "updated_at", + "updated_by": "updated_by", + "created_on": "created_at", + "created_by": "created_by" }, ) From 6f4a62dc9322f1bde74402d2309e8bcba9304ce6 Mon Sep 17 00:00:00 2001 From: anirudh-mk Date: Mon, 23 Oct 2023 00:24:35 +0530 Subject: [PATCH 8/9] feat(ig create update):validation added --- api/dashboard/ig/dash_ig_serializer.py | 72 ++++++++++++++------------ api/dashboard/ig/dash_ig_view.py | 12 ++--- db/task.py | 2 +- 3 files changed, 45 insertions(+), 41 deletions(-) diff --git a/api/dashboard/ig/dash_ig_serializer.py b/api/dashboard/ig/dash_ig_serializer.py index 30429d4e..7dd32d01 100644 --- a/api/dashboard/ig/dash_ig_serializer.py +++ b/api/dashboard/ig/dash_ig_serializer.py @@ -1,3 +1,5 @@ +import uuid + from rest_framework import serializers from db.task import InterestGroup @@ -29,20 +31,11 @@ def get_user_ig_link_ig(self, obj): return obj.user_ig_link_ig.all().count() -class InterestGroupCreateSerializer(serializers.ModelSerializer): +class InterestGroupCreateUpdateSerializer(serializers.ModelSerializer): - name = serializers.CharField( - required=True, - error_messages={ - 'required': 'code field must not be left blank.' - } - ) - icon = serializers.CharField( - required=True, - error_messages={ - 'required': 'icon field must not be left blank.' - } - ) + name = serializers.CharField(required=True) + icon = serializers.CharField(required=True) + code = serializers.CharField(required=True) class Meta: model = InterestGroup @@ -54,31 +47,42 @@ class Meta: def create(self, validated_data): user_id = self.context.get('user_id') - return InterestGroup.objects.create( - name=validated_data.get('name'), - code=validated_data.get('code'), - icon=validated_data.get('icon'), - updated_by_id=user_id, - created_by_id=user_id, - ) + validated_data['id'] = str(uuid.uuid4()) + validated_data['created_by_id'] = user_id + validated_data['updated_by_id'] = user_id -class InterestGroupUpdateSerializer(serializers.ModelSerializer): - class Meta: - model = InterestGroup - fields = [ - "name", - "code", - "icon" - ] + return InterestGroup.objects.create(**validated_data) def update(self, instance, validated_data): user_id = self.context.get('user_id') - user = User.objects.filter(id=user_id).first() - instance.name = validated_data.get('name') - instance.code = validated_data.get('code') - instance.icon = validated_data.get('icon') - instance.updated_by = user - instance.updated_at = DateTimeUtils.get_current_utc_time() + + instance.name = validated_data.get('name', instance.name) + instance.code = validated_data.get('code', instance.code) + instance.icon = validated_data.get('icon', instance.icon) + instance.updated_by_id = user_id + instance.updated_by = DateTimeUtils.get_current_utc_time() + instance.save() return instance + + def validate_name(self, name): + ig_obj = InterestGroup.objects.filter(name=name).first() + if ig_obj: + raise serializers.ValidationError("interest group with name is already exists") + if len(name) >= 75: + raise serializers.ValidationError("name should contain only 75 characters") + return name + + def validate_code(self, code): + ig_obj = InterestGroup.objects.filter(code=code).first() + if ig_obj: + raise serializers.ValidationError("interest group with code is already exists") + if len(code) >= 10: + raise serializers.ValidationError("name should contain only 75 characters") + return code + + def validate_icon(self, icon): + if len(icon) >= 75: + raise serializers.ValidationError("name should contain only 75 characters") + return icon diff --git a/api/dashboard/ig/dash_ig_view.py b/api/dashboard/ig/dash_ig_view.py index bdfa4455..f27d835b 100644 --- a/api/dashboard/ig/dash_ig_view.py +++ b/api/dashboard/ig/dash_ig_view.py @@ -8,8 +8,7 @@ from utils.utils import CommonUtils, DiscordWebhooks from .dash_ig_serializer import ( InterestGroupSerializer, - InterestGroupCreateSerializer, - InterestGroupUpdateSerializer, + InterestGroupCreateUpdateSerializer ) @@ -62,12 +61,13 @@ def get(self, request): def post(self, request): user_id = JWTUtils.fetch_user_id(request) - serializer = InterestGroupCreateSerializer( + serializer = InterestGroupCreateUpdateSerializer( data=request.data, context={ - "user_id": user_id + "user_id": user_id, } ) + if serializer.is_valid(): serializer.save() @@ -84,7 +84,7 @@ def post(self, request): ).get_success_response() return CustomResponse( - message=serializer.errors + general_message=serializer.errors ).get_failure_response() @role_required([RoleType.ADMIN.value]) @@ -95,7 +95,7 @@ def put(self, request, pk): id=pk ).name - serializer = InterestGroupUpdateSerializer( + serializer = InterestGroupCreateUpdateSerializer( data=request.data, instance=InterestGroup.objects.get( id=pk diff --git a/db/task.py b/db/task.py index 8cbbfd80..ec852369 100644 --- a/db/task.py +++ b/db/task.py @@ -34,7 +34,7 @@ class InterestGroup(models.Model): id = models.CharField(primary_key=True, max_length=36, default=uuid.uuid4) name = models.CharField(max_length=75, unique=True) code = models.CharField(max_length=10, unique=True) - icon = models.CharField(max_length=10, unique=True) + icon = models.CharField(max_length=10) updated_by = models.ForeignKey( User, on_delete=models.CASCADE, From a2f7d74dc612a2865314c5d174a25faea7de64ed Mon Sep 17 00:00:00 2001 From: anirudh-mk Date: Mon, 23 Oct 2023 00:27:05 +0530 Subject: [PATCH 9/9] feat(ig csv api):prafetch added --- api/dashboard/ig/dash_ig_view.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/api/dashboard/ig/dash_ig_view.py b/api/dashboard/ig/dash_ig_view.py index f27d835b..0cd3941f 100644 --- a/api/dashboard/ig/dash_ig_view.py +++ b/api/dashboard/ig/dash_ig_view.py @@ -152,7 +152,15 @@ class InterestGroupCSV(APIView): @role_required([RoleType.ADMIN.value]) def get(self, request): - ig_serializer = InterestGroup.objects.all() + + ig_serializer = ( + InterestGroup.objects.select_related( + "created_by", + "updated_by" + ).prefetch_related( + "user_ig_link_ig" + ).all() + ) ig_serializer_data = InterestGroupSerializer( ig_serializer,