From 1eb3f60657b2ad547707b5e18ba4b76a980dff40 Mon Sep 17 00:00:00 2001 From: jelanmathewjames Date: Wed, 13 Dec 2023 01:31:36 +0530 Subject: [PATCH 1/5] [FIX]: not updating landing stats db signals replaced signals outside consumer class created class a new class LandingStats --- api/common/common_consumer.py | 132 +++++++++++++++++----------------- 1 file changed, 64 insertions(+), 68 deletions(-) diff --git a/api/common/common_consumer.py b/api/common/common_consumer.py index 86a3e627..9858089a 100644 --- a/api/common/common_consumer.py +++ b/api/common/common_consumer.py @@ -6,6 +6,7 @@ from django.db.models.functions import Coalesce from channels.generic.websocket import WebsocketConsumer +from channels.layers import get_channel_layer from asgiref.sync import async_to_sync from db.learning_circle import LearningCircle @@ -16,47 +17,22 @@ from utils.types import IntegrationType, OrganizationType - -class GlobalCount(WebsocketConsumer): +class LandingStats: data = {} - group_name = "landing_stats" - - def connect(self): - async_to_sync(self.channel_layer.group_add)( - self.group_name, - self.channel_name - ) - self.accept() - - self.data = { - 'members': self.members_count, - 'org_type_counts': self.org_type_counts, - 'enablers_mentors_count': self.enablers_mentors_count, - 'ig_count': self.interest_groups_count, - 'learning_circle_count': self.learning_circles_count - } - self.send(text_data=json.dumps(self.data)) - - def disconnect(self, code): - self.channel_layer.group_discard(self.group_name, self.channel_name) - - @property def members_count(self): members_count = User.objects.all().count() return members_count - - @property + def org_type_counts(self): org_type_counts = Organization.objects.filter( org_type__in=[OrganizationType.COLLEGE.value, OrganizationType.COMPANY.value, - OrganizationType.COMMUNITY.value] + OrganizationType.COMMUNITY.value] ).values('org_type').annotate(org_count=Coalesce(Count('org_type'), 0)) org_type_counts = list(org_type_counts) return org_type_counts - - @property + def enablers_mentors_count(self): enablers_mentors_count = UserRoleLink.objects.filter( role__title__in=["Mentor", "Enabler"]).values( @@ -64,61 +40,81 @@ def enablers_mentors_count(self): enablers_mentors_count = list(enablers_mentors_count) return enablers_mentors_count - - @property + def interest_groups_count(self): interest_groups_count = InterestGroup.objects.all().count() return interest_groups_count - - @property + def learning_circles_count(self): learning_circles_count = LearningCircle.objects.all().count() return learning_circles_count - - def get_based_on_sender(self, sender): - if sender == User: - self.data['members'] = self.members_count + + def get_data(self, sender): + if sender == None: + self.data = { + 'members': self.members_count(), + 'org_type_counts': self.org_type_counts(), + 'enablers_mentors_count': self.enablers_mentors_count(), + 'ig_count': self.interest_groups_count(), + 'learning_circle_count': self.learning_circles_count() + } + elif sender == User: + self.data['members'] = self.members_count() elif sender == Organization: - self.data['org_type_counts'] = self.org_type_counts + self.data['org_type_counts'] = self.org_type_counts() elif sender == UserRoleLink: - self.data['enablers_mentors_count'] = self.enablers_mentors_count + self.data['enablers_mentors_count'] = self.enablers_mentors_count() elif sender == InterestGroup: - self.data['ig_count'] = self.interest_groups_count + self.data['ig_count'] = self.interest_groups_count() elif sender == LearningCircle: - self.data['learning_circle_count'] = self.learning_circles_count - - def receive(self, text_data): - - @receiver(post_save, sender=User) - @receiver(post_save, sender=LearningCircle) - @receiver(post_save, sender=InterestGroup) - @receiver(post_save, sender=UserRoleLink) - @receiver(post_save, sender=Organization) - @receiver(post_delete, sender=User) - @receiver(post_delete, sender=LearningCircle) - @receiver(post_delete, sender=InterestGroup) - @receiver(post_delete, sender=UserRoleLink) - @receiver(post_delete, sender=Organization) - def db_signals(sender, instance, created=None, *args, **kwargs): - if created: - self.get_based_on_sender(sender) - async_to_sync(self.channel_layer.group_send)( - self.group_name, - {"type": "send_data", "data": self.data} - ) - - if created == None: - self.get_based_on_sender(sender) - async_to_sync(self.channel_layer.group_send)( - self.group_name, - {"type": "send_data", "data": self.data} - ) + self.data['learning_circle_count'] = self.learning_circles_count() + + +landing_stats = LandingStats() + +class GlobalCount(WebsocketConsumer): + data = {} + group_name = "landing_stats" + + def connect(self): + async_to_sync(self.channel_layer.group_add)( + self.group_name, + self.channel_name + ) + self.accept() + + landing_stats.get_data(None) + self.data = landing_stats.data + + self.send(text_data=json.dumps(self.data)) + + def disconnect(self, code): + self.channel_layer.group_discard(self.group_name, self.channel_name) def send_data(self, event): self.send(text_data=json.dumps(event['data'])) +channel_layer = get_channel_layer() +@receiver(post_save, sender=User) +@receiver(post_save, sender=LearningCircle) +@receiver(post_save, sender=InterestGroup) +@receiver(post_save, sender=UserRoleLink) +@receiver(post_save, sender=Organization) +@receiver(post_delete, sender=User) +@receiver(post_delete, sender=LearningCircle) +@receiver(post_delete, sender=InterestGroup) +@receiver(post_delete, sender=UserRoleLink) +@receiver(post_delete, sender=Organization) +def db_signals(sender, instance, created=None, *args, **kwargs): + if created or created == None: + landing_stats.get_data(sender) + data = landing_stats.data + async_to_sync(channel_layer.group_send)( + "landing_stats", + {"type": "send_data", "data": data} + ) From 308c2e8856cd5851b5f0910e2ccc8f6dfd7cf74c Mon Sep 17 00:00:00 2001 From: lordgrim Date: Wed, 13 Dec 2023 11:23:58 +0530 Subject: [PATCH 2/5] fix(karma_voucher): handling empty events in bulk upload --- api/dashboard/karma_voucher/karma_voucher_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/dashboard/karma_voucher/karma_voucher_view.py b/api/dashboard/karma_voucher/karma_voucher_view.py index e0bc14eb..64e50129 100644 --- a/api/dashboard/karma_voucher/karma_voucher_view.py +++ b/api/dashboard/karma_voucher/karma_voucher_view.py @@ -160,7 +160,7 @@ def post(self, request): description = voucher['description'] time_or_event = f'{month}/{week}' event = voucher['event'] - if event != '': + if event != '' and event is not None: time_or_event = f'{event}/{description}' success_rows.append({ From 620bb1cb483cb55c92ae0d7c3563c84f29b7bf76 Mon Sep 17 00:00:00 2001 From: lordgrim Date: Wed, 13 Dec 2023 11:35:59 +0530 Subject: [PATCH 3/5] refactor: organising excel base templates used for bulk upload --- api/dashboard/karma_voucher/karma_voucher_view.py | 2 +- api/dashboard/organisation/organisation_views.py | 2 +- api/dashboard/roles/dash_roles_views.py | 2 +- api/dashboard/task/dash_task_view.py | 2 +- .../organisation_base_template.xlsx | Bin .../role_base_template.xlsx | Bin .../task_base_template.xlsx | Bin .../voucher_base_template.xlsx | Bin 8 files changed, 4 insertions(+), 4 deletions(-) rename {api/dashboard/organisation/assets => excel-templates}/organisation_base_template.xlsx (100%) rename {api/dashboard/roles/assets => excel-templates}/role_base_template.xlsx (100%) rename {api/dashboard/task/assets => excel-templates}/task_base_template.xlsx (100%) rename {api/dashboard/karma_voucher/assets => excel-templates}/voucher_base_template.xlsx (100%) diff --git a/api/dashboard/karma_voucher/karma_voucher_view.py b/api/dashboard/karma_voucher/karma_voucher_view.py index 64e50129..4f5b0a9e 100644 --- a/api/dashboard/karma_voucher/karma_voucher_view.py +++ b/api/dashboard/karma_voucher/karma_voucher_view.py @@ -348,7 +348,7 @@ class VoucherBaseTemplateAPI(APIView): authentication_classes = [CustomizePermission] def get(self, request): - wb = load_workbook('./api/dashboard/karma_voucher/assets/voucher_base_template.xlsx') + wb = load_workbook('./excel-templates/voucher_base_template.xlsx') ws = wb['Data Definitions'] hashtags = TaskList.objects.all().values_list('hashtag', flat=True) data = { diff --git a/api/dashboard/organisation/organisation_views.py b/api/dashboard/organisation/organisation_views.py index 1541417f..36540844 100644 --- a/api/dashboard/organisation/organisation_views.py +++ b/api/dashboard/organisation/organisation_views.py @@ -529,7 +529,7 @@ class OrganisationBaseTemplateAPI(APIView): authentication_classes = [CustomizePermission] def get(self, request): - wb = load_workbook('./api/dashboard/organisation/assets/organisation_base_template.xlsx') + wb = load_workbook('./excel-templates/organisation_base_template.xlsx') ws = wb['Data Definitions'] affiliations = OrgAffiliation.objects.all().values_list('title', flat=True) districts = District.objects.all().values_list('name', flat=True) diff --git a/api/dashboard/roles/dash_roles_views.py b/api/dashboard/roles/dash_roles_views.py index 6986ba06..d064c99e 100644 --- a/api/dashboard/roles/dash_roles_views.py +++ b/api/dashboard/roles/dash_roles_views.py @@ -298,7 +298,7 @@ class RoleBaseTemplateAPI(APIView): authentication_classes = [CustomizePermission] def get(self, request): - wb = load_workbook("./api/dashboard/roles/assets/role_base_template.xlsx") + wb = load_workbook("./excel-templates/role_base_template.xlsx") ws = wb["Data Definitions"] roles = Role.objects.all().values_list("title", flat=True) diff --git a/api/dashboard/task/dash_task_view.py b/api/dashboard/task/dash_task_view.py index 4a563e26..b2e3ea76 100644 --- a/api/dashboard/task/dash_task_view.py +++ b/api/dashboard/task/dash_task_view.py @@ -554,7 +554,7 @@ class TaskBaseTemplateAPI(APIView): authentication_classes = [CustomizePermission] def get(self, request): - wb = load_workbook('./api/dashboard/task/assets/task_base_template.xlsx') + wb = load_workbook('./excel-templates/task_base_template.xlsx') ws = wb['Data Definitions'] levels = Level.objects.all().values_list('name', flat=True) channels = Channel.objects.all().values_list('name', flat=True) diff --git a/api/dashboard/organisation/assets/organisation_base_template.xlsx b/excel-templates/organisation_base_template.xlsx similarity index 100% rename from api/dashboard/organisation/assets/organisation_base_template.xlsx rename to excel-templates/organisation_base_template.xlsx diff --git a/api/dashboard/roles/assets/role_base_template.xlsx b/excel-templates/role_base_template.xlsx similarity index 100% rename from api/dashboard/roles/assets/role_base_template.xlsx rename to excel-templates/role_base_template.xlsx diff --git a/api/dashboard/task/assets/task_base_template.xlsx b/excel-templates/task_base_template.xlsx similarity index 100% rename from api/dashboard/task/assets/task_base_template.xlsx rename to excel-templates/task_base_template.xlsx diff --git a/api/dashboard/karma_voucher/assets/voucher_base_template.xlsx b/excel-templates/voucher_base_template.xlsx similarity index 100% rename from api/dashboard/karma_voucher/assets/voucher_base_template.xlsx rename to excel-templates/voucher_base_template.xlsx From b556b1eab569e66863cc7651bd52ba0f9bea2933 Mon Sep 17 00:00:00 2001 From: lordgrim Date: Wed, 13 Dec 2023 11:53:11 +0530 Subject: [PATCH 4/5] fix(roles): webhooks in user role bulk assign --- api/dashboard/roles/dash_roles_views.py | 19 ++++++++----------- api/dashboard/roles/urls.py | 2 +- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/api/dashboard/roles/dash_roles_views.py b/api/dashboard/roles/dash_roles_views.py index d064c99e..b208467c 100644 --- a/api/dashboard/roles/dash_roles_views.py +++ b/api/dashboard/roles/dash_roles_views.py @@ -353,7 +353,6 @@ def post(self, request): excel_data = [row for row in excel_data if any(row.values())] valid_rows = [] error_rows = [] - users_to_fetch = set() roles_to_fetch = set() user_role_link_to_check = set() @@ -361,7 +360,6 @@ def post(self, request): for row in excel_data[1:]: keys_to_keep = ["muid", "role"] row_keys = list(row.keys()) - # Remove columns other than "muid" and "role" for key in row_keys: if key not in keys_to_keep: @@ -402,7 +400,6 @@ def post(self, request): user_id = users_dict.get(user) role_id = roles_dict.get(role) - if not user_id: row["muid"] = user row["role"] = role @@ -428,6 +425,7 @@ def post(self, request): row["created_by_id"] = request_user_id valid_rows.append(row) + users_by_role = {role_title: users for role_title, users in users_by_role.items() if users} user_roles_serializer = dash_roles_serializer.UserRoleBulkAssignSerializer( data=valid_rows, many=True ) @@ -441,17 +439,16 @@ def post(self, request): "role": user_role_data.get("role_id", ""), } ) + for role, user_set in users_by_role.items(): + DiscordWebhooks.general_updates( + WebHookCategory.BULK_ROLE.value, + WebHookActions.UPDATE.value, + role, + ",".join(user_set), + ) else: error_rows.append(user_roles_serializer.errors) - for role, user_set in users_by_role.items(): - DiscordWebhooks.general_updates( - WebHookCategory.BULK_ROLE.value, - WebHookActions.UPDATE.value, - role, - ",".join(user_set), - ) - return CustomResponse( response={"Success": success_data, "Failed": error_rows} ).get_success_response() diff --git a/api/dashboard/roles/urls.py b/api/dashboard/roles/urls.py index 2b90f8aa..1720c94a 100644 --- a/api/dashboard/roles/urls.py +++ b/api/dashboard/roles/urls.py @@ -8,7 +8,7 @@ path('base-template/', dash_roles_views.RoleBaseTemplateAPI.as_view(), name="roles-base-template"), path('bulk-assign/', dash_roles_views.UserRoleLinkManagement.as_view(), name="user-roles-assign"), # used to assign a bunch of users a role path('bulk-assign//', dash_roles_views.UserRoleLinkManagement.as_view(), name="user-roles-list"), # used to get the list of users to assign a role - path('bulk-assign-excel/', dash_roles_views.UserRoleBulkAssignAPI.as_view(), name="user-roles-assign-excel"), + path('bulk-assign-excel/', dash_roles_views.UserRoleBulkAssignAPI.as_view(), name="user-roles-assign-excel"), # used to bulk assign required roles to users from excel path('user-role/', dash_roles_views.UserRole.as_view(), name='create-delete-user-role'), path('', dash_roles_views.RoleAPI.as_view(), name="roles-list"), path('', dash_roles_views.RoleAPI.as_view(), name="roles-create"), From b5993bf524183dd34d4b81a215ed020dafa15158 Mon Sep 17 00:00:00 2001 From: lordgrim Date: Wed, 13 Dec 2023 13:27:00 +0530 Subject: [PATCH 5/5] fix(karma_voucher): checking event and description column headers --- api/dashboard/karma_voucher/karma_voucher_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/dashboard/karma_voucher/karma_voucher_view.py b/api/dashboard/karma_voucher/karma_voucher_view.py index 4f5b0a9e..fc101bb8 100644 --- a/api/dashboard/karma_voucher/karma_voucher_view.py +++ b/api/dashboard/karma_voucher/karma_voucher_view.py @@ -38,7 +38,7 @@ def post(self, request): if not excel_data: return CustomResponse(general_message={'Empty csv file.'}).get_failure_response() - temp_headers = ['muid', 'karma', 'hashtag', 'month', 'week'] + temp_headers = ['muid', 'karma', 'hashtag', 'month', 'week', 'description', 'event'] first_entry = excel_data[0] for key in temp_headers: if key not in first_entry: