207 lines
7.2 KiB
Python
207 lines
7.2 KiB
Python
import strawberry
|
|
from typing import List, Optional
|
|
from strawberry.types import Info
|
|
from channels.db import database_sync_to_async
|
|
from django.contrib.contenttypes.models import ContentType
|
|
|
|
from core.graphql.types.event import EventType, NotificationRuleType, NotificationType, NotificationDeliveryType
|
|
from core.models.events import Event, NotificationRule, Notification, NotificationDelivery
|
|
from core.models.enums import NotificationStatusChoices
|
|
|
|
|
|
@strawberry.type
|
|
class Query:
|
|
@strawberry.field(description="Get all events")
|
|
async def events(
|
|
self,
|
|
info: Info,
|
|
limit: Optional[int] = 50,
|
|
offset: Optional[int] = 0
|
|
) -> List[EventType]:
|
|
profile = getattr(info.context.request, 'profile', None)
|
|
if not profile:
|
|
raise PermissionError("Authentication required")
|
|
|
|
events = await database_sync_to_async(
|
|
lambda: list(Event.objects.all().order_by('-created_at')[offset:offset + limit])
|
|
)()
|
|
|
|
return events
|
|
|
|
@strawberry.field(description="Get event by ID")
|
|
async def event(
|
|
self,
|
|
info: Info,
|
|
id: strawberry.ID
|
|
) -> Optional[EventType]:
|
|
profile = getattr(info.context.request, 'profile', None)
|
|
if not profile:
|
|
raise PermissionError("Authentication required")
|
|
|
|
try:
|
|
event = await database_sync_to_async(Event.objects.get)(pk=id)
|
|
return event
|
|
except Event.DoesNotExist:
|
|
return None
|
|
|
|
@strawberry.field(description="Get all notification rules")
|
|
async def notification_rules(
|
|
self,
|
|
info: Info,
|
|
is_active: Optional[bool] = None
|
|
) -> List[NotificationRuleType]:
|
|
profile = getattr(info.context.request, 'profile', None)
|
|
if not profile:
|
|
raise PermissionError("Authentication required")
|
|
|
|
# Only admins can view notification rules
|
|
from core.models.profile import TeamProfile
|
|
from core.models.enums import RoleChoices
|
|
if not isinstance(profile, TeamProfile) or profile.role != RoleChoices.ADMIN:
|
|
raise PermissionError("Admin access required")
|
|
|
|
queryset = NotificationRule.objects.prefetch_related(
|
|
'target_team_profiles',
|
|
'target_customer_profiles'
|
|
)
|
|
if is_active is not None:
|
|
queryset = queryset.filter(is_active=is_active)
|
|
|
|
rules = await database_sync_to_async(lambda: list(queryset.order_by('name')))()
|
|
return rules
|
|
|
|
@strawberry.field(description="Get notification rule by ID")
|
|
async def notification_rule(
|
|
self,
|
|
info: Info,
|
|
id: strawberry.ID
|
|
) -> Optional[NotificationRuleType]:
|
|
profile = getattr(info.context.request, 'profile', None)
|
|
if not profile:
|
|
raise PermissionError("Authentication required")
|
|
|
|
# Only admins can view notification rules
|
|
from core.models.profile import TeamProfile
|
|
from core.models.enums import RoleChoices
|
|
if not isinstance(profile, TeamProfile) or profile.role != RoleChoices.ADMIN:
|
|
raise PermissionError("Admin access required")
|
|
|
|
try:
|
|
rule = await database_sync_to_async(
|
|
lambda: NotificationRule.objects.prefetch_related(
|
|
'target_team_profiles',
|
|
'target_customer_profiles'
|
|
).get(pk=id)
|
|
)()
|
|
return rule
|
|
except NotificationRule.DoesNotExist:
|
|
return None
|
|
|
|
@strawberry.field(description="Get notifications for current user")
|
|
async def my_notifications(
|
|
self,
|
|
info: Info,
|
|
unread_only: Optional[bool] = False,
|
|
limit: Optional[int] = 50,
|
|
offset: Optional[int] = 0
|
|
) -> List[NotificationType]:
|
|
profile = getattr(info.context.request, 'profile', None)
|
|
if not profile:
|
|
raise PermissionError("Authentication required")
|
|
|
|
@database_sync_to_async
|
|
def get_notifications():
|
|
# Get content type for the profile
|
|
content_type = ContentType.objects.get_for_model(type(profile))
|
|
|
|
# Build query
|
|
queryset = Notification.objects.filter(
|
|
recipient_content_type=content_type,
|
|
recipient_object_id=profile.id
|
|
)
|
|
|
|
if unread_only:
|
|
queryset = queryset.filter(read_at__isnull=True)
|
|
|
|
# Get notifications
|
|
return list(
|
|
queryset.select_related('event', 'rule')
|
|
.order_by('-created_at')[offset:offset + limit]
|
|
)
|
|
|
|
return await get_notifications()
|
|
|
|
@strawberry.field(description="Get unread notification count for current user")
|
|
async def my_unread_notification_count(self, info: Info) -> int:
|
|
profile = getattr(info.context.request, 'profile', None)
|
|
if not profile:
|
|
return 0
|
|
|
|
# Get content type for the profile
|
|
content_type = await database_sync_to_async(ContentType.objects.get_for_model)(profile)
|
|
|
|
# Count unread notifications
|
|
count = await database_sync_to_async(
|
|
Notification.objects.filter(
|
|
recipient_content_type=content_type,
|
|
recipient_object_id=profile.id,
|
|
read_at__isnull=True
|
|
).count
|
|
)()
|
|
|
|
return count
|
|
|
|
@strawberry.field(description="Get notification by ID")
|
|
async def notification(
|
|
self,
|
|
info: Info,
|
|
id: strawberry.ID
|
|
) -> Optional[NotificationType]:
|
|
profile = getattr(info.context.request, 'profile', None)
|
|
if not profile:
|
|
raise PermissionError("Authentication required")
|
|
|
|
@database_sync_to_async
|
|
def get_and_verify():
|
|
notification = Notification.objects.select_related('event', 'rule').get(pk=id)
|
|
|
|
# Verify user has access to this notification
|
|
content_type = ContentType.objects.get_for_model(type(profile))
|
|
|
|
if (notification.recipient_content_type != content_type or
|
|
str(notification.recipient_object_id) != str(profile.id)):
|
|
raise PermissionError("Not authorized to view this notification")
|
|
|
|
return notification
|
|
|
|
try:
|
|
return await get_and_verify()
|
|
except Notification.DoesNotExist:
|
|
return None
|
|
|
|
@strawberry.field(description="Get notification delivery status")
|
|
async def notification_deliveries(
|
|
self,
|
|
info: Info,
|
|
notification_id: strawberry.ID
|
|
) -> List[NotificationDeliveryType]:
|
|
profile = getattr(info.context.request, 'profile', None)
|
|
if not profile:
|
|
raise PermissionError("Authentication required")
|
|
|
|
# Only admins can view delivery status
|
|
from core.models.profile import TeamProfile
|
|
from core.models.enums import RoleChoices
|
|
if not isinstance(profile, TeamProfile) or profile.role != RoleChoices.ADMIN:
|
|
raise PermissionError("Admin access required")
|
|
|
|
deliveries = await database_sync_to_async(
|
|
lambda: list(
|
|
NotificationDelivery.objects.filter(notification_id=notification_id)
|
|
.select_related('notification')
|
|
.order_by('-created_at')
|
|
)
|
|
)()
|
|
|
|
return deliveries
|