207 lines
7.8 KiB
Python
207 lines
7.8 KiB
Python
from django.db import transaction
|
|
from drf_spectacular.utils import (
|
|
OpenApiExample,
|
|
OpenApiResponse,
|
|
extend_schema,
|
|
inline_serializer,
|
|
)
|
|
from rest_framework import serializers as drf_serializers
|
|
from rest_framework import status
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
|
|
from location_data.models import SoilLocation
|
|
|
|
from .models import ParameterUpdateLog, SensorData, SensorDataHistory, SensorParameter
|
|
from .serializers import (
|
|
SensorDataResponseSerializer,
|
|
SensorDataUpdateSerializer,
|
|
SensorParameterSerializer,
|
|
)
|
|
|
|
|
|
class SensorDataUpdateView(APIView):
|
|
"""
|
|
آپدیت داده سنسور. هنگام آپدیت، نسخه فعلی در SensorDataHistory ذخیره میشود.
|
|
"""
|
|
|
|
@extend_schema(
|
|
tags=["Sensor Data"],
|
|
summary="آپدیت کامل داده سنسور",
|
|
description="داده سنسور را بر اساس uuid_sensor آپدیت (یا ایجاد) میکند. نسخه قبلی در تاریخچه ذخیره میشود.",
|
|
request=SensorDataUpdateSerializer,
|
|
responses={
|
|
200: SensorDataResponseSerializer,
|
|
400: OpenApiResponse(description="داده نامعتبر"),
|
|
404: OpenApiResponse(description="location_id یافت نشد"),
|
|
},
|
|
examples=[
|
|
OpenApiExample(
|
|
"نمونه درخواست",
|
|
value={
|
|
"location_id": 1,
|
|
"soil_moisture": 45.2,
|
|
"soil_temperature": 22.5,
|
|
"soil_ph": 6.8,
|
|
"electrical_conductivity": 1.2,
|
|
"nitrogen": 30.0,
|
|
"phosphorus": 15.0,
|
|
"potassium": 20.0,
|
|
},
|
|
request_only=True,
|
|
),
|
|
],
|
|
)
|
|
def put(self, request, uuid_sensor):
|
|
return self._update(request, uuid_sensor)
|
|
|
|
@extend_schema(
|
|
tags=["Sensor Data"],
|
|
summary="آپدیت جزئی داده سنسور",
|
|
description="فقط فیلدهای ارسالشده آپدیت میشوند.",
|
|
request=SensorDataUpdateSerializer,
|
|
responses={
|
|
200: SensorDataResponseSerializer,
|
|
400: OpenApiResponse(description="داده نامعتبر"),
|
|
404: OpenApiResponse(description="location_id یافت نشد"),
|
|
},
|
|
)
|
|
def patch(self, request, uuid_sensor):
|
|
return self._update(request, uuid_sensor, partial=True)
|
|
|
|
def _update(self, request, uuid_sensor, partial=False):
|
|
serializer = SensorDataUpdateSerializer(
|
|
data=request.data, partial=partial
|
|
)
|
|
if not serializer.is_valid():
|
|
return Response(
|
|
{"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
location_id = serializer.validated_data.pop("location_id")
|
|
plant_ids = serializer.validated_data.pop("plant_ids", None)
|
|
location = SoilLocation.objects.filter(pk=location_id).first()
|
|
if not location:
|
|
return Response(
|
|
{"code": 404, "msg": "location_id یافت نشد.", "data": None},
|
|
status=status.HTTP_404_NOT_FOUND,
|
|
)
|
|
|
|
with transaction.atomic():
|
|
sensor_data, created = SensorData.objects.get_or_create(
|
|
uuid_sensor=uuid_sensor,
|
|
defaults={"location": location, **serializer.validated_data},
|
|
)
|
|
|
|
if not created:
|
|
# آپدیت رکورد اصلی
|
|
for key, value in serializer.validated_data.items():
|
|
setattr(sensor_data, key, value)
|
|
sensor_data.save()
|
|
|
|
# ذخیره نسخه جدید (همان مقادیر جدول اصلی) در تاریخچه
|
|
SensorDataHistory.objects.create(
|
|
uuid_sensor=sensor_data.uuid_sensor,
|
|
location_id=sensor_data.location_id,
|
|
soil_moisture=sensor_data.soil_moisture,
|
|
soil_temperature=sensor_data.soil_temperature,
|
|
soil_ph=sensor_data.soil_ph,
|
|
electrical_conductivity=sensor_data.electrical_conductivity,
|
|
nitrogen=sensor_data.nitrogen,
|
|
phosphorus=sensor_data.phosphorus,
|
|
potassium=sensor_data.potassium,
|
|
)
|
|
|
|
if plant_ids is not None:
|
|
sensor_data.plants.set(plant_ids)
|
|
|
|
return Response(
|
|
{
|
|
"code": 200,
|
|
"msg": "success",
|
|
"data": SensorDataResponseSerializer(sensor_data).data,
|
|
},
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
|
|
|
|
class SensorParameterCreateView(APIView):
|
|
"""
|
|
اضافه کردن پارامتر جدید و ثبت در ParameterUpdateLog.
|
|
"""
|
|
|
|
@extend_schema(
|
|
tags=["Sensor Parameters"],
|
|
summary="افزودن/ویرایش پارامتر سنسور",
|
|
description="پارامتر جدید اضافه یا پارامتر موجود را ویرایش میکند و در لاگ ثبت میشود.",
|
|
request=SensorParameterSerializer,
|
|
responses={
|
|
201: inline_serializer(
|
|
name="SensorParameterResponse",
|
|
fields={
|
|
"code": drf_serializers.IntegerField(),
|
|
"msg": drf_serializers.CharField(),
|
|
"data": inline_serializer(
|
|
name="SensorParameterData",
|
|
fields={
|
|
"id": drf_serializers.IntegerField(),
|
|
"code": drf_serializers.CharField(),
|
|
"name_fa": drf_serializers.CharField(),
|
|
"unit": drf_serializers.CharField(),
|
|
"created_at": drf_serializers.DateTimeField(),
|
|
"action": drf_serializers.CharField(),
|
|
},
|
|
),
|
|
},
|
|
),
|
|
400: OpenApiResponse(description="داده نامعتبر"),
|
|
},
|
|
examples=[
|
|
OpenApiExample(
|
|
"نمونه درخواست",
|
|
value={"code": "soil_moisture", "name_fa": "رطوبت خاک", "unit": "%"},
|
|
request_only=True,
|
|
),
|
|
],
|
|
)
|
|
def post(self, request):
|
|
serializer = SensorParameterSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(
|
|
{"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
code = serializer.validated_data["code"]
|
|
name_fa = serializer.validated_data["name_fa"]
|
|
unit = serializer.validated_data.get("unit", "")
|
|
|
|
with transaction.atomic():
|
|
parameter, created = SensorParameter.objects.update_or_create(
|
|
code=code,
|
|
defaults={"name_fa": name_fa, "unit": unit},
|
|
)
|
|
action = (
|
|
ParameterUpdateLog.ACTION_ADDED
|
|
if created
|
|
else ParameterUpdateLog.ACTION_MODIFIED
|
|
)
|
|
ParameterUpdateLog.objects.create(parameter=parameter, action=action)
|
|
|
|
return Response(
|
|
{
|
|
"code": 201,
|
|
"msg": "success",
|
|
"data": {
|
|
"id": parameter.id,
|
|
"code": parameter.code,
|
|
"name_fa": parameter.name_fa,
|
|
"unit": parameter.unit,
|
|
"created_at": parameter.created_at,
|
|
"action": action,
|
|
},
|
|
},
|
|
status=status.HTTP_201_CREATED,
|
|
)
|