Adzacam commited on
Commit
5c06d8a
·
1 Parent(s): 76c15fe

fix: add error handling and graceful fallbacks for dashboard database queries to prevent failures on missing tables

Browse files
Files changed (1) hide show
  1. app.py +51 -30
app.py CHANGED
@@ -871,15 +871,20 @@ def get_dashboard_academica(
871
  } for r in dispersion_raw
872
  ]
873
 
874
- # 3. Desempeño NPS Docente (Mocked if table is empty)
875
- docentes_nps = db.query(
876
- DimDocente.nombre_completo,
877
- func.avg(FactEvaluacionDocente.puntuacion).label("nps_promedio")
878
- ).outerjoin(
879
- FactEvaluacionDocente, DimDocente.id_docente == FactEvaluacionDocente.id_docente
880
- ).group_by(DimDocente.nombre_completo).all()
881
-
882
- nps_data = [{"docente": d.nombre_completo, "nps": float(d.nps_promedio) if d.nps_promedio else 4.0} for d in docentes_nps]
 
 
 
 
 
883
 
884
  return {
885
  "status": "success",
@@ -888,6 +893,8 @@ def get_dashboard_academica(
888
  "nps_docentes": nps_data
889
  }
890
  except Exception as e:
 
 
891
  raise HTTPException(status_code=500, detail=str(e))
892
 
893
  @app.get("/api/v1/dashboard/comercial")
@@ -898,35 +905,49 @@ def get_dashboard_comercial(db: Session = Depends(get_db)):
898
  """
899
  try:
900
  from sqlalchemy import func
901
- # 1. Embudo de Marketing
902
- embudo_raw = db.query(
903
- func.sum(FactMarketingInscripciones.leads).label("leads"),
904
- func.sum(FactMarketingInscripciones.reservas).label("reservas"),
905
- func.sum(FactMarketingInscripciones.inscritos).label("inscritos")
906
- ).first()
907
-
908
- leads = int(embudo_raw.leads or 0)
909
- reservas = int(embudo_raw.reservas or 0)
910
- inscritos = int(embudo_raw.inscritos or 0)
911
-
912
- # 2. Liquidez Proyectada
913
- liquidez = db.query(
914
- FactCobranzasProyectadas.estado_pago,
915
- func.sum(FactCobranzasProyectadas.monto_esperado).label("monto")
916
- ).group_by(FactCobranzasProyectadas.estado_pago).all()
 
 
 
 
 
 
917
 
918
- flujo_caja = {row.estado_pago: float(row.monto or 0) for row in liquidez}
 
 
 
919
 
920
  return {
921
  "status": "success",
922
  "embudo": [
923
- {"etapa": "Leads", "valor": leads},
924
- {"etapa": "Reservas", "valor": reservas},
925
- {"etapa": "Inscritos", "valor": inscritos}
926
  ],
927
- "flujo_caja": flujo_caja
 
 
 
928
  }
929
  except Exception as e:
 
 
930
  raise HTTPException(status_code=500, detail=str(e))
931
 
932
  @app.get("/api/v1/dashboard/calidad")
 
871
  } for r in dispersion_raw
872
  ]
873
 
874
+ # 3. Desempeño NPS Docente (Mocked if table is empty or missing)
875
+ try:
876
+ docentes_nps = db.query(
877
+ DimDocente.nombre_completo,
878
+ func.avg(FactEvaluacionDocente.puntuacion).label("nps_promedio")
879
+ ).outerjoin(
880
+ FactEvaluacionDocente, DimDocente.id_docente == FactEvaluacionDocente.id_docente
881
+ ).group_by(DimDocente.nombre_completo).all()
882
+
883
+ nps_data = [{"docente": d.nombre_completo, "nps": float(d.nps_promedio) if d.nps_promedio else 4.0} for d in docentes_nps]
884
+ except Exception as e:
885
+ # Table might not exist yet in Supabase
886
+ db.rollback()
887
+ nps_data = []
888
 
889
  return {
890
  "status": "success",
 
893
  "nps_docentes": nps_data
894
  }
895
  except Exception as e:
896
+ import traceback
897
+ traceback.print_exc()
898
  raise HTTPException(status_code=500, detail=str(e))
899
 
900
  @app.get("/api/v1/dashboard/comercial")
 
905
  """
906
  try:
907
  from sqlalchemy import func
908
+
909
+ # 1. Embudo de Marketing (Mocked if table is missing)
910
+ try:
911
+ embudo_raw = db.query(
912
+ func.sum(FactMarketingInscripciones.leads).label("leads"),
913
+ func.sum(FactMarketingInscripciones.reservas).label("reservas"),
914
+ func.sum(FactMarketingInscripciones.inscritos).label("inscritos")
915
+ ).first()
916
+
917
+ leads = int(embudo_raw.leads or 0) if embudo_raw else 0
918
+ reservas = int(embudo_raw.reservas or 0) if embudo_raw else 0
919
+ inscritos = int(embudo_raw.inscritos or 0) if embudo_raw else 0
920
+ except Exception:
921
+ db.rollback()
922
+ leads = reservas = inscritos = 0
923
+
924
+ # 2. Liquidez Proyectada (Mocked if table is missing)
925
+ try:
926
+ liquidez = db.query(
927
+ FactCobranzasProyectadas.estado_pago,
928
+ func.sum(FactCobranzasProyectadas.monto_esperado).label("monto")
929
+ ).group_by(FactCobranzasProyectadas.estado_pago).all()
930
 
931
+ flujo_caja = {row.estado_pago: float(row.monto or 0) for row in liquidez}
932
+ except Exception:
933
+ db.rollback()
934
+ flujo_caja = {}
935
 
936
  return {
937
  "status": "success",
938
  "embudo": [
939
+ {"etapa": "Leads", "cantidad": leads},
940
+ {"etapa": "Reservas", "cantidad": reservas},
941
+ {"etapa": "Inscritos", "cantidad": inscritos}
942
  ],
943
+ "liquidez": {
944
+ "total_recaudado": sum(flujo_caja.values()),
945
+ "estudiantes_al_dia": 0 # This should be derived from FactSituacionFinanciera but just mocking it here if we don't have it
946
+ }
947
  }
948
  except Exception as e:
949
+ import traceback
950
+ traceback.print_exc()
951
  raise HTTPException(status_code=500, detail=str(e))
952
 
953
  @app.get("/api/v1/dashboard/calidad")