from __future__ import annotations import json from rest_framework import serializers class QueryJSONField(serializers.JSONField): def to_internal_value(self, data): if isinstance(data, str): data = data.strip() if not data: return None try: data = json.loads(data) except json.JSONDecodeError as exc: raise serializers.ValidationError("فرمت JSON نامعتبر است.") from exc return super().to_internal_value(data) class GrowthSimulationRequestSerializer(serializers.Serializer): plant_name = serializers.CharField(help_text="نام گیاه") dynamic_parameters = serializers.ListField( child=serializers.CharField(), allow_empty=False, help_text="پارامترهای متغیر رشد که باید در خروجی گزارش شوند.", ) farm_uuid = serializers.UUIDField(required=False, allow_null=True) weather = serializers.JSONField(required=False) soil_parameters = serializers.JSONField(required=False) site_parameters = serializers.JSONField(required=False) crop_parameters = serializers.JSONField(required=False) agromanagement = serializers.JSONField(required=False) irrigation_recommendation = serializers.JSONField(required=False) fertilization_recommendation = serializers.JSONField(required=False) page_size = serializers.IntegerField(required=False, min_value=1, max_value=50) def validate(self, attrs): if not attrs.get("farm_uuid") and not attrs.get("weather"): raise serializers.ValidationError( "یکی از farm_uuid یا weather باید ارسال شود." ) return attrs class GrowthSimulationQueuedSerializer(serializers.Serializer): task_id = serializers.CharField() status_url = serializers.CharField() plant_name = serializers.CharField() class GrowthStageMetricSerializer(serializers.Serializer): start = serializers.FloatField() end = serializers.FloatField() min = serializers.FloatField() max = serializers.FloatField() avg = serializers.FloatField() class GrowthStageSerializer(serializers.Serializer): order = serializers.IntegerField() stage_code = serializers.CharField() stage_name = serializers.CharField() start_date = serializers.DateField() end_date = serializers.DateField() days_count = serializers.IntegerField() metrics = serializers.JSONField() class GrowthPaginationSerializer(serializers.Serializer): page = serializers.IntegerField() page_size = serializers.IntegerField() total_items = serializers.IntegerField() total_pages = serializers.IntegerField() has_next = serializers.BooleanField() has_previous = serializers.BooleanField() class GrowthSimulationResultSerializer(serializers.Serializer): plant_name = serializers.CharField() dynamic_parameters = serializers.ListField(child=serializers.CharField()) engine = serializers.CharField(allow_null=True) model_name = serializers.CharField(allow_null=True) scenario_id = serializers.IntegerField(allow_null=True) simulation_warning = serializers.CharField(allow_null=True, allow_blank=True) summary_metrics = serializers.JSONField() stage_timeline = GrowthStageSerializer(many=True) stages_page = GrowthStageSerializer(many=True) pagination = GrowthPaginationSerializer() daily_records_count = serializers.IntegerField() default_page_size = serializers.IntegerField() class CurrentFarmChartRequestSerializer(serializers.Serializer): farm_uuid = serializers.UUIDField(help_text="شناسه یکتای مزرعه") plant_name = serializers.CharField(required=False, allow_blank=True, help_text="نام گیاه") irrigation_recommendation = serializers.JSONField(required=False) fertilization_recommendation = serializers.JSONField(required=False) class CurrentFarmChartResponseSerializer(serializers.Serializer): farm_uuid = serializers.CharField(allow_null=True) plant_name = serializers.CharField() engine = serializers.CharField(allow_null=True) model_name = serializers.CharField(allow_null=True) scenario_id = serializers.IntegerField(allow_null=True) simulation_warning = serializers.CharField(allow_null=True, allow_blank=True) categories = serializers.ListField(child=serializers.CharField()) series = serializers.JSONField() summary = serializers.JSONField() current_state = serializers.JSONField() metrics = serializers.JSONField() daily_output = serializers.JSONField() class HarvestPredictionRequestSerializer(serializers.Serializer): farm_uuid = serializers.UUIDField(help_text="شناسه یکتای مزرعه") plant_name = serializers.CharField(required=False, allow_blank=True, help_text="نام گیاه") irrigation_recommendation = serializers.JSONField(required=False) fertilization_recommendation = serializers.JSONField(required=False) class HarvestPredictionResponseSerializer(serializers.Serializer): date = serializers.CharField() dateFormatted = serializers.CharField() daysUntil = serializers.IntegerField() description = serializers.CharField() optimalWindowStart = serializers.CharField() optimalWindowEnd = serializers.CharField() gddDetails = serializers.JSONField() class YieldPredictionRequestSerializer(serializers.Serializer): farm_uuid = serializers.UUIDField(help_text="شناسه یکتای مزرعه") plant_name = serializers.CharField(required=False, allow_blank=True, help_text="نام گیاه") irrigation_recommendation = serializers.JSONField(required=False) fertilization_recommendation = serializers.JSONField(required=False) class YieldPredictionResponseSerializer(serializers.Serializer): farm_uuid = serializers.CharField() plant_name = serializers.CharField(allow_null=True) predictedYieldTons = serializers.FloatField() predictedYieldRaw = serializers.FloatField() unit = serializers.CharField() sourceUnit = serializers.CharField() simulationEngine = serializers.CharField(allow_null=True) simulationModel = serializers.CharField(allow_null=True) scenarioId = serializers.IntegerField(allow_null=True) simulationWarning = serializers.CharField(allow_null=True, allow_blank=True) supportingMetrics = serializers.JSONField() class YieldHarvestSummaryQuerySerializer(serializers.Serializer): farm_uuid = serializers.UUIDField(required=True, help_text="شناسه یکتای مزرعه") season_year = serializers.IntegerField(required=False, help_text="سال زراعی") crop_name = serializers.CharField(required=False, allow_blank=True, help_text="نام محصول") include_narrative = serializers.BooleanField( required=False, default=False, help_text="در صورت true بودن، بخش روایت نیز در آینده اضافه می شود.", ) irrigation_recommendation = QueryJSONField( required=False, allow_null=True, help_text="برنامه آبیاری به صورت JSON برای تزریق به PCSE.", ) fertilization_recommendation = QueryJSONField( required=False, allow_null=True, help_text="برنامه کودهی به صورت JSON برای تزریق به PCSE.", ) class YieldHarvestSummaryResponseSerializer(serializers.Serializer): farm_uuid = serializers.CharField() season_highlights_card = serializers.JSONField() yield_prediction = serializers.JSONField() harvest_prediction_card = serializers.JSONField() harvest_readiness_zones = serializers.JSONField() yield_quality_bands = serializers.JSONField() harvest_operations_card = serializers.JSONField() yield_prediction_chart = serializers.JSONField()