|
|
|
@ -4,10 +4,16 @@ from rest_framework.authentication import TokenAuthentication |
|
|
|
from drf_yasg.utils import swagger_auto_schema |
|
|
|
from drf_yasg import openapi |
|
|
|
from rest_framework.permissions import IsAuthenticated |
|
|
|
from apps.account.serializers import NotificationSerializer, NotificationSendSerializer |
|
|
|
from apps.account.serializers import NotificationSerializer, NotificationSendSerializer, AdminNotificationSerializer |
|
|
|
from apps.account.models import Notification, User |
|
|
|
from apps.account.tasks import send_notification |
|
|
|
from utils.pagination import StandardResultsSetPagination |
|
|
|
from django.db.models import Q |
|
|
|
from rest_framework.viewsets import ModelViewSet |
|
|
|
from apps.account.permissions import IsSuperAdmin |
|
|
|
import logging |
|
|
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -63,49 +69,22 @@ class NotificationReadAllView(generics.GenericAPIView): |
|
|
|
authentication_classes = [TokenAuthentication] |
|
|
|
queryset = Notification.objects.all() |
|
|
|
|
|
|
|
|
|
|
|
@swagger_auto_schema( |
|
|
|
operation_description="Mark all notifications as read for the authenticated user or merchant account.", |
|
|
|
operation_description="Mark all notifications as read for the authenticated user.", |
|
|
|
tags=['Notifications'], |
|
|
|
manual_parameters=[ |
|
|
|
openapi.Parameter( |
|
|
|
'service', |
|
|
|
openapi.IN_QUERY, |
|
|
|
description="Filter notifications to mark as read by service (imam-javad or doboodi)", |
|
|
|
type=openapi.TYPE_STRING, |
|
|
|
enum=['imam-javad', 'doboodi'], |
|
|
|
required=False |
|
|
|
) |
|
|
|
], |
|
|
|
responses={ |
|
|
|
200: "All notifications marked as read", |
|
|
|
} |
|
|
|
) |
|
|
|
def get(self, request, *args, **kwargs): |
|
|
|
user = request.user |
|
|
|
service = request.query_params.get('service', None) |
|
|
|
|
|
|
|
# Get base queryset for user's notifications |
|
|
|
notifications = Notification.objects.filter(user=user) |
|
|
|
# Mark all of the user's notifications as read |
|
|
|
Notification.objects.filter(user=user).update(is_read=True) |
|
|
|
|
|
|
|
return Response({'status': 'all notifications marked as read'}, status=status.HTTP_200_OK) |
|
|
|
|
|
|
|
|
|
|
|
# Apply service filtering based on query parameter |
|
|
|
if service == 'doboodi': |
|
|
|
# If service is doboodi, only mark doboodi notifications as read |
|
|
|
notifications = notifications.filter(service=Notification.ServiceChoices.DOBOODI) |
|
|
|
status_message = 'all doboodi notifications marked as read' |
|
|
|
else: |
|
|
|
# Default: mark all imam-javad notifications as read (exclude doboodi) |
|
|
|
notifications = notifications.exclude(service=Notification.ServiceChoices.DOBOODI) |
|
|
|
status_message = 'all imam-javad notifications marked as read' |
|
|
|
|
|
|
|
# Update the filtered notifications |
|
|
|
notifications.update(is_read=True) |
|
|
|
|
|
|
|
return Response({'status': status_message}, status=status.HTTP_200_OK) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SendNotificationView(generics.GenericAPIView): |
|
|
|
|
|
|
|
@swagger_auto_schema( |
|
|
|
@ -157,3 +136,109 @@ class SendNotificationView(generics.GenericAPIView): |
|
|
|
return Response({ |
|
|
|
'error': str(e) |
|
|
|
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) |
|
|
|
|
|
|
|
|
|
|
|
class AdminNotificationViewSet(ModelViewSet): |
|
|
|
permission_classes = [IsSuperAdmin] |
|
|
|
authentication_classes = [TokenAuthentication] |
|
|
|
serializer_class = AdminNotificationSerializer |
|
|
|
pagination_class = StandardResultsSetPagination |
|
|
|
|
|
|
|
def get_queryset(self): |
|
|
|
queryset = Notification.objects.all().select_related('user') |
|
|
|
|
|
|
|
# Filter by service if provided |
|
|
|
service = self.request.query_params.get('service', None) |
|
|
|
if service: |
|
|
|
queryset = queryset.filter(service=service) |
|
|
|
|
|
|
|
# Search by user name or email or notification title/message |
|
|
|
search = self.request.query_params.get('search', None) |
|
|
|
if search: |
|
|
|
queryset = queryset.filter( |
|
|
|
Q(title__icontains=search) | |
|
|
|
Q(message__icontains=search) | |
|
|
|
Q(user__fullname__icontains=search) | |
|
|
|
Q(user__email__icontains=search) |
|
|
|
) |
|
|
|
|
|
|
|
# Date filtering |
|
|
|
date_after = self.request.query_params.get('date_after', None) |
|
|
|
if date_after: |
|
|
|
queryset = queryset.filter(created_at__date__gte=date_after) |
|
|
|
|
|
|
|
date_before = self.request.query_params.get('date_before', None) |
|
|
|
if date_before: |
|
|
|
queryset = queryset.filter(created_at__date__lte=date_before) |
|
|
|
|
|
|
|
# User filtering |
|
|
|
user_param = self.request.query_params.get('user', None) |
|
|
|
if user_param: |
|
|
|
queryset = queryset.filter(user_id=user_param) |
|
|
|
|
|
|
|
# Read status filtering (is_read=true/false) |
|
|
|
is_read_param = self.request.query_params.get('is_read', None) |
|
|
|
if is_read_param is not None: |
|
|
|
if is_read_param.lower() == 'true': |
|
|
|
queryset = queryset.filter(is_read=True) |
|
|
|
elif is_read_param.lower() == 'false': |
|
|
|
queryset = queryset.filter(is_read=False) |
|
|
|
|
|
|
|
return queryset.order_by('-created_at') |
|
|
|
|
|
|
|
def create(self, request, *args, **kwargs): |
|
|
|
title = request.data.get('title') |
|
|
|
message = request.data.get('message') |
|
|
|
service = request.data.get('service', 'imam-javad') |
|
|
|
send_to_all = request.data.get('send_to_all', False) |
|
|
|
user_id = request.data.get('user_id', None) |
|
|
|
|
|
|
|
if not title or not message: |
|
|
|
return Response({'error': 'Title and message are required.'}, status=status.HTTP_400_BAD_REQUEST) |
|
|
|
|
|
|
|
if send_to_all: |
|
|
|
# Get all active users |
|
|
|
users = User.objects.filter(is_active=True) |
|
|
|
notifications_to_create = [] |
|
|
|
for u in users: |
|
|
|
notifications_to_create.append(Notification( |
|
|
|
title=title, |
|
|
|
message=message, |
|
|
|
service=service, |
|
|
|
user=u |
|
|
|
)) |
|
|
|
Notification.objects.bulk_create(notifications_to_create) |
|
|
|
|
|
|
|
# Send push notifications |
|
|
|
fcm_tokens = list(users.exclude(fcm__isnull=True).exclude(fcm='').values_list('fcm', flat=True)) |
|
|
|
if fcm_tokens: |
|
|
|
try: |
|
|
|
send_notification(fcm_tokens, title, message, {'service': service}) |
|
|
|
except Exception as e: |
|
|
|
logger.error(f"Failed to send push notifications: {e}") |
|
|
|
|
|
|
|
return Response({'message': f'Notification created for {len(notifications_to_create)} users.'}, status=status.HTTP_201_CREATED) |
|
|
|
else: |
|
|
|
if not user_id: |
|
|
|
return Response({'error': 'user_id is required when send_to_all is false.'}, status=status.HTTP_400_BAD_REQUEST) |
|
|
|
try: |
|
|
|
user = User.objects.get(id=user_id) |
|
|
|
except User.DoesNotExist: |
|
|
|
return Response({'error': 'User not found.'}, status=status.HTTP_404_NOT_FOUND) |
|
|
|
|
|
|
|
notif = Notification.objects.create( |
|
|
|
title=title, |
|
|
|
message=message, |
|
|
|
service=service, |
|
|
|
user=user |
|
|
|
) |
|
|
|
|
|
|
|
# Send push notification |
|
|
|
if user.fcm: |
|
|
|
try: |
|
|
|
send_notification([user.fcm], title, message, {'service': service}) |
|
|
|
except Exception as e: |
|
|
|
logger.error(f"Failed to send push notification: {e}") |
|
|
|
|
|
|
|
serializer = self.get_serializer(notif) |
|
|
|
return Response(serializer.data, status=status.HTTP_201_CREATED) |