""" Notifications API routes. """ from typing import List, Optional import csv from datetime import datetime from ninja import Router from ninja_jwt.authentication import JWTAuth from ninja.pagination import paginate, PageNumberPagination from django.shortcuts import get_object_or_404 from django.http import HttpResponse from django.utils import timezone from .models import Notification from .utils import get_notification_preference from .schemas import ( NotificationOut, UnreadCountOut, MessageOut, NotificationPreferenceOut, NotificationPreferenceIn, ) router = Router() @router.get("/", response=List[NotificationOut], auth=JWTAuth()) @paginate(PageNumberPagination, page_size=20) def list_notifications( request, is_read: Optional[bool] = None, type: Optional[str] = None, start: Optional[datetime] = None, end: Optional[datetime] = None, ): """Get current user's notifications.""" queryset = Notification.objects.filter(user=request.auth) if is_read is not None: queryset = queryset.filter(is_read=is_read) if type: queryset = queryset.filter(type=type) if start: queryset = queryset.filter(created_at__gte=start) if end: queryset = queryset.filter(created_at__lte=end) return [ NotificationOut( id=n.id, user_id=n.user_id, type=n.type, title=n.title, content=n.content, related_id=n.related_id, related_type=n.related_type, is_read=n.is_read, created_at=n.created_at, ) for n in queryset ] @router.get("/preferences/", response=NotificationPreferenceOut, auth=JWTAuth()) def get_preferences(request): """Get current user's notification preferences.""" preference = get_notification_preference(request.auth) return NotificationPreferenceOut( user_id=preference.user_id, enable_bounty=preference.enable_bounty, enable_price_alert=preference.enable_price_alert, enable_system=preference.enable_system, updated_at=preference.updated_at, ) @router.patch("/preferences/", response=NotificationPreferenceOut, auth=JWTAuth()) def update_preferences(request, data: NotificationPreferenceIn): """Update notification preferences.""" preference = get_notification_preference(request.auth) update_data = data.dict(exclude_unset=True) for key, value in update_data.items(): setattr(preference, key, value) preference.save() return NotificationPreferenceOut( user_id=preference.user_id, enable_bounty=preference.enable_bounty, enable_price_alert=preference.enable_price_alert, enable_system=preference.enable_system, updated_at=preference.updated_at, ) @router.get("/unread-count/", response=UnreadCountOut, auth=JWTAuth()) def get_unread_count(request): """Get count of unread notifications.""" count = Notification.objects.filter(user=request.auth, is_read=False).count() return UnreadCountOut(count=count) @router.get("/export/", auth=JWTAuth()) def export_notifications_csv(request): """Export current user's notifications to CSV.""" notifications = Notification.objects.filter(user=request.auth).order_by("-created_at") response = HttpResponse(content_type="text/csv; charset=utf-8") filename = f'notifications_{timezone.now().strftime("%Y%m%d_%H%M%S")}.csv' response["Content-Disposition"] = f'attachment; filename="{filename}"' response.write("\ufeff") writer = csv.writer(response) writer.writerow(["created_at", "type", "title", "content", "is_read"]) for notification in notifications: writer.writerow( [ notification.created_at.isoformat(), notification.type, notification.title, notification.content or "", "true" if notification.is_read else "false", ] ) return response @router.post("/{notification_id}/read/", response=MessageOut, auth=JWTAuth()) def mark_as_read(request, notification_id: int): """Mark a notification as read.""" notification = get_object_or_404( Notification, id=notification_id, user=request.auth ) notification.is_read = True notification.save() return MessageOut(message="已标记为已读", success=True) @router.post("/read-all/", response=MessageOut, auth=JWTAuth()) def mark_all_as_read(request): """Mark all notifications as read.""" Notification.objects.filter(user=request.auth, is_read=False).update(is_read=True) return MessageOut(message="已全部标记为已读", success=True) @router.delete("/{notification_id}", response=MessageOut, auth=JWTAuth()) def delete_notification(request, notification_id: int): """Delete a notification.""" notification = get_object_or_404( Notification, id=notification_id, user=request.auth ) notification.delete() return MessageOut(message="通知已删除", success=True) @router.delete("/", response=MessageOut, auth=JWTAuth()) def delete_all_read(request): """Delete all read notifications.""" Notification.objects.filter(user=request.auth, is_read=True).delete() return MessageOut(message="已删除所有已读通知", success=True)