This commit is contained in:
2026-04-25 17:22:41 +03:30
parent 569d520a5c
commit aa24fc22b0
124 changed files with 8491 additions and 2582 deletions
+83
View File
@@ -0,0 +1,83 @@
from __future__ import annotations
from typing import Any
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)
plants = list(sensor.plants.all()) if hasattr(sensor, "plants") else []
plant = plants[0] if plants else None
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("plants")
.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"),
},
"knowledge_base": insight.get("knowledge_base"),
"tone_file": insight.get("tone_file"),
"raw_response": insight.get("raw_response"),
}