from django.utils import timezone from .ai_bundle import request_dashboard_ai_bundle from .card_utils import is_fresh, ttl_for_card from .cards.anomaly_detection_card import build_anomaly_detection_card from .cards.economic_overview import build_economic_overview from .cards.farm_alerts_timeline import build_farm_alerts_timeline from .cards.farm_alerts_tracker import build_farm_alerts_tracker from .cards.farm_overview_kpis import build_farm_overview_kpis from .cards.farm_weather_card import build_farm_weather_card from .cards.harvest_prediction_card import build_harvest_prediction_card from .cards.ndvi_health_card import build_ndvi_health_card from .cards.recommendations_list import build_recommendations_list from .cards.sensor_comparison_chart import build_sensor_comparison_chart from .cards.sensor_radar_chart import build_sensor_radar_chart from .cards.sensor_values_list import build_sensor_values_list from .cards.soil_moisture_heatmap import build_soil_moisture_heatmap from .cards.water_need_prediction import build_water_need_prediction from .cards.yield_prediction_chart import build_yield_prediction_chart from .context import load_dashboard_context from .models import DashboardCardSnapshot CARD_BUILDERS = { "farmOverviewKpis": build_farm_overview_kpis, "farmWeatherCard": build_farm_weather_card, "farmAlertsTracker": build_farm_alerts_tracker, "sensorValuesList": build_sensor_values_list, "sensorRadarChart": build_sensor_radar_chart, "sensorComparisonChart": build_sensor_comparison_chart, "anomalyDetectionCard": build_anomaly_detection_card, "farmAlertsTimeline": build_farm_alerts_timeline, "waterNeedPrediction": build_water_need_prediction, "harvestPredictionCard": build_harvest_prediction_card, "yieldPredictionChart": build_yield_prediction_chart, "soilMoistureHeatmap": build_soil_moisture_heatmap, "ndviHealthCard": build_ndvi_health_card, "recommendationsList": build_recommendations_list, "economicOverview": build_economic_overview, } AI_DRIVEN_CARDS = { "farmAlertsTimeline", "recommendationsList", } def build_dashboard_payload(sensor_id: str) -> dict: context = load_dashboard_context(sensor_id) if context is None: return {} ai_payload_request = { "sensor_id": sensor_id, "cards": sorted(AI_DRIVEN_CARDS), } ai_bundle = request_dashboard_ai_bundle(sensor_id=sensor_id, payload=ai_payload_request) return { card_name: builder(sensor_id=sensor_id, context=context, ai_bundle=ai_bundle) for card_name, builder in CARD_BUILDERS.items() } def get_or_build_card(sensor_id: str, card_name: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict: latest_snapshot = ( DashboardCardSnapshot.objects.filter(sensor_id=sensor_id, card_name=card_name) .order_by("-generated_at") .first() ) if is_fresh(latest_snapshot): return latest_snapshot.payload payload = CARD_BUILDERS[card_name](sensor_id=sensor_id, context=context, ai_bundle=ai_bundle) DashboardCardSnapshot.objects.create( sensor_id=sensor_id, card_name=card_name, payload=payload, expires_at=timezone.now() + ttl_for_card(card_name), source="ai" if card_name in AI_DRIVEN_CARDS else "computed", ) return payload def build_dashboard_payload_with_cache(sensor_id: str) -> dict: context = load_dashboard_context(sensor_id) if context is None: return {} ai_payload_request = { "sensor_id": sensor_id, "cards": sorted(AI_DRIVEN_CARDS), } ai_bundle = request_dashboard_ai_bundle(sensor_id=sensor_id, payload=ai_payload_request) payload = {} for card_name in CARD_BUILDERS: payload[card_name] = get_or_build_card( sensor_id=sensor_id, card_name=card_name, context=context, ai_bundle=ai_bundle, ) return payload