Files
Backend/notifications/views.py
T

116 lines
4.2 KiB
Python
Raw Normal View History

2026-04-05 04:20:58 +03:30
from django.conf import settings
from drf_spectacular.utils import OpenApiParameter, OpenApiTypes, extend_schema
2026-04-05 00:57:25 +03:30
from rest_framework import serializers, status
2026-04-05 04:20:58 +03:30
from rest_framework.permissions import AllowAny, IsAuthenticated
2026-04-03 23:51:00 +03:30
from rest_framework.response import Response
from rest_framework.views import APIView
from config.swagger import code_response
2026-04-05 00:57:25 +03:30
from farm_hub.models import FarmHub
from .serializers import FarmNotificationSerializer
2026-04-05 04:20:58 +03:30
from .services import long_poll_notifications, mark_notifications_as_read
2026-04-05 00:57:25 +03:30
2026-04-03 23:51:00 +03:30
2026-04-05 00:57:25 +03:30
class NotificationLongPollQuerySerializer(serializers.Serializer):
farm_uuid = serializers.UUIDField()
since_id = serializers.IntegerField(required=False, min_value=1)
timeout = serializers.IntegerField(required=False, min_value=0, max_value=60)
2026-04-03 23:51:00 +03:30
2026-04-05 04:20:58 +03:30
class NotificationMarkReadSerializer(serializers.Serializer):
2026-04-05 00:57:25 +03:30
farm_uuid = serializers.UUIDField()
2026-04-05 04:20:58 +03:30
slice_id = serializers.IntegerField(min_value=1)
def get_owned_farm(*, farm_uuid, user):
return FarmHub.objects.filter(farm_uuid=farm_uuid, owner=user).first()
2026-04-03 23:51:00 +03:30
2026-04-05 00:57:25 +03:30
class NotificationLongPollView(APIView):
2026-04-03 23:51:00 +03:30
permission_classes = [IsAuthenticated]
@extend_schema(
tags=["Notifications"],
2026-04-05 00:57:25 +03:30
parameters=[NotificationLongPollQuerySerializer],
responses={
200: code_response("NotificationLongPollResponse", data=FarmNotificationSerializer(many=True)),
404: code_response("NotificationLongPollNotFoundResponse"),
503: code_response("NotificationLongPollNotificationsUnavailableResponse"),
},
2026-04-03 23:51:00 +03:30
)
def get(self, request):
2026-04-05 00:57:25 +03:30
serializer = NotificationLongPollQuerySerializer(data=request.query_params)
serializer.is_valid(raise_exception=True)
2026-04-03 23:51:00 +03:30
2026-04-05 04:20:58 +03:30
farm = get_owned_farm(
2026-04-05 00:57:25 +03:30
farm_uuid=serializer.validated_data["farm_uuid"],
2026-04-05 04:20:58 +03:30
user=request.user,
)
2026-04-05 00:57:25 +03:30
if farm is None:
return Response({"code": 404, "msg": "Farm not found."}, status=status.HTTP_404_NOT_FOUND)
2026-04-03 23:51:00 +03:30
2026-04-05 00:57:25 +03:30
try:
notifications = long_poll_notifications(
farm=farm,
since_id=serializer.validated_data.get("since_id"),
timeout_seconds=serializer.validated_data.get("timeout", 15),
)
except ValueError as exc:
if str(exc) == "Notifications table is not migrated.":
return Response(
{"code": 503, "msg": "Notifications table is not ready. Run migrations."},
status=status.HTTP_503_SERVICE_UNAVAILABLE,
)
raise
data = FarmNotificationSerializer(notifications, many=True).data
return Response({"code": 200, "msg": "success", "data": data}, status=status.HTTP_200_OK)
2026-04-03 23:51:00 +03:30
2026-04-05 04:20:58 +03:30
class NotificationMarkReadView(APIView):
permission_classes = [IsAuthenticated]
@extend_schema(
tags=["Notifications"],
request=NotificationMarkReadSerializer,
responses={
200: code_response(
"NotificationMarkReadResponse",
extra_fields={"marked_count": serializers.IntegerField()},
),
404: code_response("NotificationMarkReadNotFoundResponse"),
503: code_response("NotificationMarkReadUnavailableResponse"),
},
)
def post(self, request):
serializer = NotificationMarkReadSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
farm = get_owned_farm(
farm_uuid=serializer.validated_data["farm_uuid"],
user=request.user,
)
if farm is None:
return Response({"code": 404, "msg": "Farm not found."}, status=status.HTTP_404_NOT_FOUND)
try:
marked_count = mark_notifications_as_read(
farm=farm,
slice_id=serializer.validated_data["slice_id"],
)
except ValueError as exc:
if str(exc) == "Notifications table is not migrated.":
return Response(
{"code": 503, "msg": "Notifications table is not ready. Run migrations."},
status=status.HTTP_503_SERVICE_UNAVAILABLE,
)
raise
return Response(
{"code": 200, "msg": "success", "marked_count": marked_count},
status=status.HTTP_200_OK,
)