from __future__ import annotations from typing import Any from farm_data.services import clone_snapshot_as_runtime_plant, get_primary_plant_snapshot from irrigation.evapotranspiration import calculate_forecast_water_needs, resolve_crop_profile from farm_data.models import SensorData from rag.services import get_water_need_prediction_insight from .services import get_forecast_for_location def build_water_need_prediction_payload(*, sensor: Any, forecasts: list[Any]) -> dict[str, Any]: location = getattr(sensor, "center_location", None) plant = clone_snapshot_as_runtime_plant(get_primary_plant_snapshot(sensor)) irrigation_method = getattr(sensor, "irrigation_method", None) if not forecasts or location is None: return { "totalNext7Days": 0, "unit": "mm", "categories": [], "series": [], "dailyBreakdown": [], "cropProfile": {}, "irrigationEfficiencyPercent": None, } crop_profile = resolve_crop_profile(plant) efficiency = getattr(irrigation_method, "water_efficiency_percent", None) if irrigation_method else None daily = calculate_forecast_water_needs( forecasts=forecasts[:7], latitude_deg=float(location.latitude), crop_profile=crop_profile, growth_stage=crop_profile.get("current_stage"), irrigation_efficiency_percent=efficiency, ) daily_requirements = [round(item["gross_irrigation_mm"], 2) for item in daily] return { "totalNext7Days": round(sum(daily_requirements), 2), "unit": "mm", "categories": [f"روز {index}" for index in range(1, len(daily_requirements) + 1)], "series": [{"name": "نیاز آبی تعدیل‌شده", "data": daily_requirements}], "dailyBreakdown": daily, "cropProfile": crop_profile, "irrigationEfficiencyPercent": efficiency, } class WaterNeedPredictionService: def get_water_need_prediction(self, *, farm_uuid: str) -> dict[str, Any]: sensor = ( SensorData.objects.select_related("center_location", "irrigation_method") .prefetch_related("plant_assignments__plant") .filter(farm_uuid=farm_uuid) .first() ) if sensor is None: raise ValueError("Farm not found.") forecasts = get_forecast_for_location(sensor.center_location, days=7) payload = build_water_need_prediction_payload(sensor=sensor, forecasts=forecasts) insight = get_water_need_prediction_insight( farm_uuid=farm_uuid, prediction_payload=payload, ) return { "farm_uuid": farm_uuid, **payload, "insight": { "summary": insight.get("summary"), "irrigation_outlook": insight.get("irrigation_outlook"), "recommended_action": insight.get("recommended_action"), "risk_note": insight.get("risk_note"), "confidence": insight.get("confidence"), }, "raw_response": insight.get("raw_response"), }