UPDATE
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import FarmHub, FarmSensor, FarmType, Product
|
||||
|
||||
|
||||
class FarmTypeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = FarmType
|
||||
fields = ["uuid", "name", "description", "metadata"]
|
||||
|
||||
|
||||
class ProductSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Product
|
||||
fields = ["uuid", "name", "description", "metadata"]
|
||||
|
||||
|
||||
class FarmSensorSerializer(serializers.ModelSerializer):
|
||||
last_updated = serializers.DateTimeField(source="updated_at", read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = FarmSensor
|
||||
fields = [
|
||||
"uuid",
|
||||
"name",
|
||||
"sensor_type",
|
||||
"is_active",
|
||||
"specifications",
|
||||
"power_source",
|
||||
"customization",
|
||||
"last_updated",
|
||||
]
|
||||
read_only_fields = ["uuid", "last_updated"]
|
||||
|
||||
|
||||
class FarmHubSerializer(serializers.ModelSerializer):
|
||||
last_updated = serializers.DateTimeField(source="updated_at", read_only=True)
|
||||
farm_type = FarmTypeSerializer(read_only=True)
|
||||
products = ProductSerializer(many=True, read_only=True)
|
||||
sensors = FarmSensorSerializer(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = FarmHub
|
||||
fields = [
|
||||
"farm_uuid",
|
||||
"name",
|
||||
"is_active",
|
||||
"customization",
|
||||
"farm_type",
|
||||
"products",
|
||||
"sensors",
|
||||
"last_updated",
|
||||
]
|
||||
read_only_fields = ["farm_uuid", "last_updated"]
|
||||
|
||||
|
||||
class FarmSensorWriteSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = FarmSensor
|
||||
fields = [
|
||||
"name",
|
||||
"sensor_type",
|
||||
"is_active",
|
||||
"specifications",
|
||||
"power_source",
|
||||
"customization",
|
||||
]
|
||||
|
||||
|
||||
class FarmHubCreateSerializer(serializers.ModelSerializer):
|
||||
area_geojson = serializers.JSONField(write_only=True, required=False)
|
||||
farm_type_uuid = serializers.UUIDField(write_only=True)
|
||||
product_uuids = serializers.ListField(
|
||||
child=serializers.UUIDField(),
|
||||
write_only=True,
|
||||
allow_empty=False,
|
||||
)
|
||||
sensors = FarmSensorWriteSerializer(many=True, required=False)
|
||||
|
||||
class Meta:
|
||||
model = FarmHub
|
||||
fields = [
|
||||
"name",
|
||||
"is_active",
|
||||
"customization",
|
||||
"farm_type_uuid",
|
||||
"product_uuids",
|
||||
"sensors",
|
||||
"area_geojson",
|
||||
]
|
||||
|
||||
def validate_area_geojson(self, value):
|
||||
if not isinstance(value, dict):
|
||||
raise serializers.ValidationError("`area_geojson` must be a GeoJSON object.")
|
||||
|
||||
geometry = value.get("geometry") if value.get("type") == "Feature" else value
|
||||
if not isinstance(geometry, dict):
|
||||
raise serializers.ValidationError("`area_geojson.geometry` is required.")
|
||||
|
||||
if geometry.get("type") != "Polygon":
|
||||
raise serializers.ValidationError("`area_geojson.geometry.type` must be `Polygon`.")
|
||||
|
||||
coordinates = geometry.get("coordinates")
|
||||
if not isinstance(coordinates, list) or not coordinates or not isinstance(coordinates[0], list):
|
||||
raise serializers.ValidationError("`area_geojson.geometry.coordinates` must be a polygon ring.")
|
||||
|
||||
return value
|
||||
|
||||
def validate(self, attrs):
|
||||
farm_type_uuid = attrs.get("farm_type_uuid")
|
||||
product_uuids = attrs.get("product_uuids")
|
||||
|
||||
if farm_type_uuid is None:
|
||||
if self.instance is None:
|
||||
raise serializers.ValidationError({"farm_type_uuid": ["This field is required."]})
|
||||
farm_type = self.instance.farm_type
|
||||
else:
|
||||
try:
|
||||
farm_type = FarmType.objects.get(uuid=farm_type_uuid)
|
||||
except FarmType.DoesNotExist as exc:
|
||||
raise serializers.ValidationError({"farm_type_uuid": ["Farm type not found."]}) from exc
|
||||
|
||||
if product_uuids is None:
|
||||
products = list(self.instance.products.all()) if self.instance is not None else []
|
||||
else:
|
||||
products = list(Product.objects.filter(uuid__in=product_uuids))
|
||||
if len(products) != len(product_uuids):
|
||||
raise serializers.ValidationError({"product_uuids": ["One or more products were not found."]})
|
||||
|
||||
invalid_products = [product.name for product in products if product.farm_type_id != farm_type.id]
|
||||
if invalid_products:
|
||||
raise serializers.ValidationError(
|
||||
{"product_uuids": [f"Products must belong to farm type `{farm_type.name}`."]}
|
||||
)
|
||||
|
||||
attrs["farm_type"] = farm_type
|
||||
attrs["products"] = products
|
||||
return attrs
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data.pop("area_geojson", None)
|
||||
sensors_data = validated_data.pop("sensors", [])
|
||||
products = validated_data.pop("products", [])
|
||||
validated_data["farm_type"] = validated_data.pop("farm_type")
|
||||
validated_data.pop("farm_type_uuid", None)
|
||||
validated_data.pop("product_uuids", None)
|
||||
|
||||
farm = super().create(validated_data)
|
||||
if products:
|
||||
farm.products.set(products)
|
||||
if sensors_data:
|
||||
FarmSensor.objects.bulk_create([FarmSensor(farm=farm, **sensor_data) for sensor_data in sensors_data])
|
||||
return farm
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
validated_data.pop("area_geojson", None)
|
||||
sensors_data = validated_data.pop("sensors", None)
|
||||
products = validated_data.pop("products", None)
|
||||
farm_type = validated_data.pop("farm_type", None)
|
||||
validated_data.pop("farm_type_uuid", None)
|
||||
validated_data.pop("product_uuids", None)
|
||||
|
||||
for attr, value in validated_data.items():
|
||||
setattr(instance, attr, value)
|
||||
if farm_type is not None:
|
||||
instance.farm_type = farm_type
|
||||
instance.save()
|
||||
|
||||
if products is not None:
|
||||
instance.products.set(products)
|
||||
if sensors_data is not None:
|
||||
instance.sensors.all().delete()
|
||||
if sensors_data:
|
||||
FarmSensor.objects.bulk_create([FarmSensor(farm=instance, **sensor_data) for sensor_data in sensors_data])
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
class FarmToggleSerializer(serializers.Serializer):
|
||||
farm_uuid = serializers.UUIDField()
|
||||
Reference in New Issue
Block a user