UPDATE
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
from drf_spectacular.utils import OpenApiParameter, extend_schema
|
||||
from rest_framework.exceptions import NotFound
|
||||
from rest_framework import serializers, status
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from farm_hub.models import FarmHub
|
||||
|
||||
from .enums import FARMER_TAG_ITEMS
|
||||
from .models import FarmerCalendarEvent
|
||||
from .serializers import (
|
||||
FarmerCalendarEventResponseSerializer,
|
||||
FarmerCalendarEventWriteSerializer,
|
||||
FarmerCalendarListQuerySerializer,
|
||||
FarmerCalendarTagIdSerializer,
|
||||
)
|
||||
|
||||
|
||||
class FarmerCalendarBaseView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@staticmethod
|
||||
def error_response(message, details=None, code="EVENT_VALIDATION_ERROR", status_code=status.HTTP_400_BAD_REQUEST):
|
||||
payload = {
|
||||
"code": code,
|
||||
"message": message,
|
||||
}
|
||||
if details is not None:
|
||||
payload["details"] = details
|
||||
return Response(payload, status=status_code)
|
||||
|
||||
def handle_exception(self, exc):
|
||||
if isinstance(exc, serializers.ValidationError):
|
||||
details = exc.detail
|
||||
message = "Invalid event payload"
|
||||
if isinstance(details, dict):
|
||||
first_value = next(iter(details.values()), None)
|
||||
if isinstance(first_value, list) and first_value:
|
||||
message = str(first_value[0])
|
||||
elif first_value:
|
||||
message = str(first_value)
|
||||
elif isinstance(details, list) and details:
|
||||
message = str(details[0])
|
||||
return self.error_response(message=message, details=details)
|
||||
if isinstance(exc, NotFound):
|
||||
return self.error_response(
|
||||
message=str(exc.detail),
|
||||
code="EVENT_NOT_FOUND",
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
)
|
||||
return super().handle_exception(exc)
|
||||
|
||||
def _get_user_farms(self, request):
|
||||
return FarmHub.objects.filter(owner=request.user).order_by("id")
|
||||
|
||||
def _resolve_farm(self, request, farm_uuid=None, required=False):
|
||||
farms = self._get_user_farms(request)
|
||||
if farm_uuid:
|
||||
try:
|
||||
return farms.get(farm_uuid=farm_uuid)
|
||||
except FarmHub.DoesNotExist as exc:
|
||||
raise serializers.ValidationError({"farm_uuid": ["Farm not found."]}) from exc
|
||||
|
||||
if required:
|
||||
farm_count = farms.count()
|
||||
if farm_count == 1:
|
||||
return farms.first()
|
||||
if farm_count == 0:
|
||||
raise serializers.ValidationError({"farm_uuid": ["No farm found for this user."]})
|
||||
raise serializers.ValidationError({"farm_uuid": ["farm_uuid is required when multiple farms exist."]})
|
||||
return None
|
||||
|
||||
def _get_event(self, request, event_id):
|
||||
queryset = FarmerCalendarEvent.objects.select_related("farm").prefetch_related("tags")
|
||||
try:
|
||||
return queryset.get(uuid=event_id, farm__owner=request.user)
|
||||
except FarmerCalendarEvent.DoesNotExist as exc:
|
||||
raise NotFound("Event not found.") from exc
|
||||
|
||||
|
||||
class EventListCreateView(FarmerCalendarBaseView):
|
||||
@extend_schema(
|
||||
tags=["Farmer Calendar"],
|
||||
parameters=[
|
||||
OpenApiParameter(name="start", type=OpenApiTypes.DATETIME, location=OpenApiParameter.QUERY, required=False),
|
||||
OpenApiParameter(name="end", type=OpenApiTypes.DATETIME, location=OpenApiParameter.QUERY, required=False),
|
||||
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=False),
|
||||
],
|
||||
)
|
||||
def get(self, request):
|
||||
query_serializer = FarmerCalendarListQuerySerializer(data=request.query_params)
|
||||
query_serializer.is_valid(raise_exception=True)
|
||||
|
||||
queryset = FarmerCalendarEvent.objects.filter(farm__owner=request.user).prefetch_related("tags")
|
||||
farm = self._resolve_farm(request, query_serializer.validated_data.get("farm_uuid"), required=False)
|
||||
if farm is not None:
|
||||
queryset = queryset.filter(farm=farm)
|
||||
|
||||
start = query_serializer.validated_data.get("start")
|
||||
end = query_serializer.validated_data.get("end")
|
||||
if start:
|
||||
queryset = queryset.filter(end__gte=start)
|
||||
if end:
|
||||
queryset = queryset.filter(start__lte=end)
|
||||
|
||||
events = queryset.order_by("start", "created_at")
|
||||
data = FarmerCalendarEventResponseSerializer(events, many=True).data
|
||||
return Response({"events": data, "meta": {"total": len(data)}}, status=status.HTTP_200_OK)
|
||||
|
||||
@extend_schema(tags=["Farmer Calendar"])
|
||||
def post(self, request):
|
||||
serializer = FarmerCalendarEventWriteSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
farm = self._resolve_farm(request, serializer.validated_data.get("farm_uuid"), required=True)
|
||||
event = serializer.save(farm=farm)
|
||||
data = FarmerCalendarEventResponseSerializer(event).data
|
||||
return Response({"event": data}, status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
class EventTagListView(FarmerCalendarBaseView):
|
||||
@extend_schema(
|
||||
tags=["Farmer Calendar"],
|
||||
parameters=[
|
||||
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=False),
|
||||
],
|
||||
)
|
||||
def get(self, request):
|
||||
self._resolve_farm(request, request.query_params.get("farm_uuid"), required=False)
|
||||
data = FarmerCalendarTagIdSerializer(FARMER_TAG_ITEMS, many=True).data
|
||||
return Response({"tags": data, "meta": {"total": len(data)}}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class EventDetailView(FarmerCalendarBaseView):
|
||||
@extend_schema(tags=["Farmer Calendar"])
|
||||
def get(self, request, event_id):
|
||||
event = self._get_event(request, event_id)
|
||||
data = FarmerCalendarEventResponseSerializer(event).data
|
||||
return Response({"event": data}, status=status.HTTP_200_OK)
|
||||
|
||||
@extend_schema(tags=["Farmer Calendar"])
|
||||
def put(self, request, event_id):
|
||||
event = self._get_event(request, event_id)
|
||||
serializer = FarmerCalendarEventWriteSerializer(event, data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
requested_farm_uuid = serializer.validated_data.get("farm_uuid")
|
||||
if requested_farm_uuid and str(event.farm.farm_uuid) != str(requested_farm_uuid):
|
||||
return self.error_response(
|
||||
message="farm_uuid cannot change an existing event",
|
||||
details={"farm_uuid": ["farm_uuid cannot change an existing event"]},
|
||||
)
|
||||
|
||||
event = serializer.save()
|
||||
data = FarmerCalendarEventResponseSerializer(event).data
|
||||
return Response({"event": data}, status=status.HTTP_200_OK)
|
||||
|
||||
@extend_schema(tags=["Farmer Calendar"])
|
||||
def delete(self, request, event_id):
|
||||
event = self._get_event(request, event_id)
|
||||
event.delete()
|
||||
return Response({"success": True}, status=status.HTTP_200_OK)
|
||||
Reference in New Issue
Block a user