2026-02-19 16:58:41 +03:30
|
|
|
"""
|
|
|
|
|
Farm Dashboard API views.
|
|
|
|
|
"""
|
|
|
|
|
|
2026-04-02 23:25:39 +03:30
|
|
|
from rest_framework import serializers, status
|
|
|
|
|
from rest_framework.permissions import IsAuthenticated
|
2026-02-19 16:58:41 +03:30
|
|
|
from rest_framework.response import Response
|
|
|
|
|
from rest_framework.views import APIView
|
2026-04-02 23:25:39 +03:30
|
|
|
from drf_spectacular.types import OpenApiTypes
|
|
|
|
|
from drf_spectacular.utils import OpenApiParameter, extend_schema, extend_schema_view
|
2026-02-19 16:58:41 +03:30
|
|
|
|
2026-03-24 20:10:48 +03:30
|
|
|
from config.swagger import code_response
|
2026-04-02 23:25:39 +03:30
|
|
|
from external_api_adapter import request as external_api_request
|
|
|
|
|
from farm_hub.models import FarmHub
|
|
|
|
|
from .mock_data import DEFAULT_CONFIG
|
|
|
|
|
from .models import FarmDashboardConfig
|
2026-03-26 15:39:31 +03:30
|
|
|
from .serializers import FarmDashboardConfigPatchSerializer, FarmDashboardConfigSerializer
|
2026-02-19 16:58:41 +03:30
|
|
|
|
|
|
|
|
|
2026-04-02 23:25:39 +03:30
|
|
|
class FarmAccessMixin:
|
|
|
|
|
@staticmethod
|
|
|
|
|
def _get_farm(request, farm_uuid):
|
|
|
|
|
if not farm_uuid:
|
|
|
|
|
raise serializers.ValidationError({"farm_uuid": ["This field is required."]})
|
|
|
|
|
try:
|
|
|
|
|
return FarmHub.objects.get(farm_uuid=farm_uuid, owner=request.user)
|
|
|
|
|
except FarmHub.DoesNotExist as exc:
|
|
|
|
|
raise serializers.ValidationError({"farm_uuid": ["Farm not found."]}) from exc
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def _get_or_create_dashboard_config(farm):
|
|
|
|
|
config, _created = FarmDashboardConfig.objects.get_or_create(
|
|
|
|
|
farm=farm,
|
|
|
|
|
defaults={
|
|
|
|
|
"disabled_card_ids": DEFAULT_CONFIG["disabled_card_ids"],
|
|
|
|
|
"row_order": DEFAULT_CONFIG["row_order"],
|
|
|
|
|
"enable_drag_reorder": DEFAULT_CONFIG["enable_drag_reorder"],
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
return config
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def _serialize_config(config):
|
|
|
|
|
return {
|
|
|
|
|
"farm_uuid": str(config.farm.farm_uuid),
|
|
|
|
|
"disabled_card_ids": config.disabled_card_ids,
|
|
|
|
|
"row_order": config.row_order,
|
|
|
|
|
"enable_drag_reorder": config.enable_drag_reorder,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-03-24 20:10:48 +03:30
|
|
|
@extend_schema_view(
|
|
|
|
|
get=extend_schema(
|
|
|
|
|
tags=["Farm Dashboard"],
|
2026-04-02 23:25:39 +03:30
|
|
|
parameters=[
|
|
|
|
|
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=True),
|
|
|
|
|
],
|
2026-03-26 15:39:31 +03:30
|
|
|
responses={200: code_response("FarmDashboardConfigGetResponse", data=FarmDashboardConfigSerializer())},
|
2026-03-24 20:10:48 +03:30
|
|
|
),
|
|
|
|
|
patch=extend_schema(
|
|
|
|
|
tags=["Farm Dashboard"],
|
2026-03-26 15:39:31 +03:30
|
|
|
request=FarmDashboardConfigPatchSerializer,
|
|
|
|
|
responses={200: code_response("FarmDashboardConfigPatchResponse", data=FarmDashboardConfigSerializer())},
|
2026-03-24 20:10:48 +03:30
|
|
|
),
|
|
|
|
|
)
|
2026-04-02 23:25:39 +03:30
|
|
|
class FarmDashboardConfigView(FarmAccessMixin, APIView):
|
2026-02-19 16:58:41 +03:30
|
|
|
"""
|
2026-03-26 15:39:31 +03:30
|
|
|
Farm dashboard config endpoints.
|
2026-04-02 23:25:39 +03:30
|
|
|
GET/PATCH are persisted in DB per farm.
|
2026-02-19 16:58:41 +03:30
|
|
|
"""
|
2026-04-02 23:25:39 +03:30
|
|
|
|
|
|
|
|
permission_classes = [IsAuthenticated]
|
2026-04-03 23:51:00 +03:30
|
|
|
required_feature_code = "greenhouse-dashboard"
|
2026-03-26 15:39:31 +03:30
|
|
|
|
2026-02-19 16:58:41 +03:30
|
|
|
def get(self, request):
|
2026-04-02 23:25:39 +03:30
|
|
|
farm = self._get_farm(request, request.query_params.get("farm_uuid"))
|
|
|
|
|
config = self._get_or_create_dashboard_config(farm)
|
|
|
|
|
return Response(
|
|
|
|
|
{"code": 200, "msg": "OK", "data": self._serialize_config(config)},
|
|
|
|
|
status=status.HTTP_200_OK,
|
|
|
|
|
)
|
2026-02-19 16:58:41 +03:30
|
|
|
|
|
|
|
|
def patch(self, request):
|
2026-03-26 15:39:31 +03:30
|
|
|
serializer = FarmDashboardConfigPatchSerializer(data=request.data)
|
|
|
|
|
serializer.is_valid(raise_exception=True)
|
2026-04-02 23:25:39 +03:30
|
|
|
|
|
|
|
|
farm = self._get_farm(request, serializer.validated_data["farm_uuid"])
|
|
|
|
|
config = self._get_or_create_dashboard_config(farm)
|
|
|
|
|
|
|
|
|
|
update_fields = ["updated_at"]
|
|
|
|
|
if "disabled_card_ids" in serializer.validated_data:
|
|
|
|
|
config.disabled_card_ids = serializer.validated_data["disabled_card_ids"]
|
|
|
|
|
update_fields.append("disabled_card_ids")
|
|
|
|
|
if "row_order" in serializer.validated_data:
|
|
|
|
|
config.row_order = serializer.validated_data["row_order"]
|
|
|
|
|
update_fields.append("row_order")
|
|
|
|
|
if "enable_drag_reorder" in serializer.validated_data:
|
|
|
|
|
config.enable_drag_reorder = serializer.validated_data["enable_drag_reorder"]
|
|
|
|
|
update_fields.append("enable_drag_reorder")
|
|
|
|
|
config.save(update_fields=update_fields)
|
|
|
|
|
|
2026-03-26 15:39:31 +03:30
|
|
|
return Response(
|
2026-04-02 23:25:39 +03:30
|
|
|
{"code": 200, "msg": "OK", "data": self._serialize_config(config)},
|
2026-03-26 15:39:31 +03:30
|
|
|
status=status.HTTP_200_OK,
|
|
|
|
|
)
|
2026-02-19 16:58:41 +03:30
|
|
|
|
|
|
|
|
|
2026-03-24 20:10:48 +03:30
|
|
|
@extend_schema_view(
|
|
|
|
|
get=extend_schema(
|
|
|
|
|
tags=["Farm Dashboard"],
|
2026-04-02 23:25:39 +03:30
|
|
|
parameters=[
|
|
|
|
|
OpenApiParameter(name="farm_uuid", type=OpenApiTypes.UUID, location=OpenApiParameter.QUERY, required=True),
|
|
|
|
|
],
|
2026-03-24 20:10:48 +03:30
|
|
|
responses={200: code_response("FarmDashboardCardsResponse", data=serializers.JSONField())},
|
|
|
|
|
),
|
|
|
|
|
)
|
2026-04-02 23:25:39 +03:30
|
|
|
class FarmDashboardCardsView(FarmAccessMixin, APIView):
|
2026-02-19 16:58:41 +03:30
|
|
|
"""
|
|
|
|
|
Farm dashboard cards endpoint: GET.
|
2026-04-02 23:25:39 +03:30
|
|
|
Requires farm_uuid and forwards it to the external AI service.
|
2026-02-19 16:58:41 +03:30
|
|
|
"""
|
2026-03-26 15:39:31 +03:30
|
|
|
|
2026-04-02 23:25:39 +03:30
|
|
|
permission_classes = [IsAuthenticated]
|
2026-04-03 23:51:00 +03:30
|
|
|
required_feature_code = "greenhouse-dashboard"
|
2026-04-02 23:25:39 +03:30
|
|
|
|
|
|
|
|
def get(self, request):
|
|
|
|
|
farm = self._get_farm(request, request.query_params.get("farm_uuid"))
|
|
|
|
|
adapter_response = external_api_request(
|
|
|
|
|
"ai",
|
|
|
|
|
"/dashboard-data/status",
|
|
|
|
|
method="GET",
|
|
|
|
|
query={"farm_uuid": str(farm.farm_uuid)},
|
|
|
|
|
)
|
2026-03-25 00:51:04 +03:30
|
|
|
return Response(adapter_response.data, status=adapter_response.status_code)
|