From b7409f2ab7f7e54477a10fc71927ddb6638930c4 Mon Sep 17 00:00:00 2001 From: mohsentaba Date: Sat, 17 Oct 2026 16:53:35 +0330 Subject: [PATCH] feat(support): filter active rooms with messages and clean up rooms of deleted users - Delete associated SupportRoom on User.soft_delete() - Add cleanup_deleted_or_inactive_support_rooms to purge inactive/soft-deleted users' rooms - Filter admin rooms list and total unread counter to active users with messages only - Apply active_support_rooms_queryset filter to room retrieval and reply endpoints --- apps/account/models/user.py | 3 +++ apps/support/views.py | 45 +++++++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/apps/account/models/user.py b/apps/account/models/user.py index fddbdb3..553430d 100644 --- a/apps/account/models/user.py +++ b/apps/account/models/user.py @@ -100,6 +100,9 @@ class User(AbstractUser): return f"{username}" def soft_delete(self): + from apps.support.models import SupportRoom + + SupportRoom.objects.filter(user=self).delete() self.deleted_at = timezone.now() self.is_active = False self.fullname = f'{self.fullname}:deleted' diff --git a/apps/support/views.py b/apps/support/views.py index 64422e1..9bb4d64 100644 --- a/apps/support/views.py +++ b/apps/support/views.py @@ -40,8 +40,45 @@ class IsSupportAdminPanelUser(BasePermission): return getattr(user, 'user_type', None) in ('super_admin', 'admin', 'professor', 'consultant') +def cleanup_deleted_or_inactive_support_rooms() -> None: + """ + Deletes SupportRooms belonging to users who have been soft-deleted or deactivated. + """ + SupportRoom.objects.filter( + Q(user__is_active=False) + | Q(user__deleted_at__isnull=False) + | Q(user__fullname__endswith=':deleted') + ).delete() + + +def active_support_rooms_queryset(): + """ + Returns SupportRooms belonging only to active, non-deleted users (including active guest users) + that have at least one message. + """ + cleanup_deleted_or_inactive_support_rooms() + return ( + SupportRoom.objects.filter( + user__is_active=True, + user__deleted_at__isnull=True, + messages__isnull=False, + ) + .exclude(user__fullname__endswith=':deleted') + .distinct() + ) + + def get_total_admin_unread_count() -> int: - agg = SupportRoom.objects.aggregate(total=Sum('unread_by_admin')) + agg = ( + SupportRoom.objects.filter( + user__is_active=True, + user__deleted_at__isnull=True, + messages__isnull=False, + ) + .exclude(user__fullname__endswith=':deleted') + .distinct() + .aggregate(total=Sum('unread_by_admin')) + ) return int(agg.get('total') or 0) @@ -191,7 +228,7 @@ class AdminSupportRoomListView(APIView): search = (request.query_params.get('search') or '').strip() - qs = SupportRoom.objects.select_related('user', 'assigned_to').order_by( + qs = active_support_rooms_queryset().select_related('user', 'assigned_to').order_by( '-last_message_at', '-updated_at', '-id', @@ -302,7 +339,7 @@ class AdminSupportRoomMessagesView(APIView): def get(self, request, room_id: int, *args, **kwargs): room = get_object_or_404( - SupportRoom.objects.select_related('user', 'assigned_to'), + active_support_rooms_queryset().select_related('user', 'assigned_to'), pk=room_id, ) @@ -357,7 +394,7 @@ class AdminSupportRoomMessagesView(APIView): @transaction.atomic def post(self, request, room_id: int, *args, **kwargs): room = get_object_or_404( - SupportRoom.objects.select_related('user', 'assigned_to'), + active_support_rooms_queryset().select_related('user', 'assigned_to'), pk=room_id, ) serializer = SendSupportMessageSerializer(data=request.data)