2026-01-26 11:09:40 -05:00

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