## Backend Changes - Add new API endpoints: combustible, pois, mantenimiento, video, configuracion - Fix vehiculos endpoint to return paginated response with items array - Add /vehiculos/all endpoint for non-paginated list - Add /geocercas/all endpoint - Add /alertas/configuracion GET/PUT endpoints - Add /viajes/activos and /viajes/iniciar endpoints - Add /reportes/stats, /reportes/templates, /reportes/preview endpoints - Add /conductores/all and /conductores/disponibles endpoints - Update router.py to include all new modules ## Frontend Changes - Fix authentication token handling (snake_case vs camelCase) - Update vehiculosApi.listAll to use /vehiculos/all - Fix FuelGauge component usage in Combustible page - Fix chart component exports (named + default exports) - Update API client for proper token refresh ## Infrastructure - Rename services from ADAN to ATLAS - Configure Cloudflare tunnel for atlas.consultoria-as.com - Update systemd service files - Configure PostgreSQL with TimescaleDB - Configure Redis, Mosquitto, Traccar, MediaMTX ## Documentation - Update installation guides - Update API reference - Rename all ADAN references to ATLAS Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
304 lines
8.3 KiB
Python
304 lines
8.3 KiB
Python
"""
|
|
Endpoints para reportes y dashboard.
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.core.database import get_db
|
|
from app.core.security import get_current_user
|
|
from app.models.usuario import Usuario
|
|
from app.schemas.reporte import (
|
|
DashboardResumen,
|
|
DashboardGrafico,
|
|
ReporteRequest,
|
|
ReporteResponse,
|
|
)
|
|
from app.services.reporte_service import ReporteService
|
|
|
|
router = APIRouter(prefix="/reportes", tags=["Reportes"])
|
|
|
|
|
|
@router.get("/stats")
|
|
async def obtener_estadisticas_reportes(
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: Usuario = Depends(get_current_user),
|
|
):
|
|
"""Obtiene estadísticas de reportes generados."""
|
|
return {
|
|
"total_generados": 0,
|
|
"ultimo_mes": 0,
|
|
"por_tipo": {
|
|
"viajes": 0,
|
|
"alertas": 0,
|
|
"combustible": 0,
|
|
"mantenimiento": 0,
|
|
}
|
|
}
|
|
|
|
|
|
@router.get("/templates")
|
|
async def listar_plantillas_reportes(
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: Usuario = Depends(get_current_user),
|
|
):
|
|
"""Lista las plantillas de reportes disponibles."""
|
|
return [
|
|
{"id": "viajes", "nombre": "Reporte de Viajes", "descripcion": "Detalle de viajes realizados"},
|
|
{"id": "alertas", "nombre": "Reporte de Alertas", "descripcion": "Resumen de alertas generadas"},
|
|
{"id": "combustible", "nombre": "Reporte de Combustible", "descripcion": "Consumo y cargas de combustible"},
|
|
{"id": "mantenimiento", "nombre": "Reporte de Mantenimiento", "descripcion": "Estado de mantenimientos"},
|
|
{"id": "resumen", "nombre": "Reporte Resumen", "descripcion": "Resumen general de la flota"},
|
|
]
|
|
|
|
|
|
@router.post("/preview")
|
|
async def previsualizar_reporte(
|
|
request: ReporteRequest,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: Usuario = Depends(get_current_user),
|
|
):
|
|
"""Previsualiza un reporte sin generarlo completamente."""
|
|
reporte_service = ReporteService(db)
|
|
datos = await reporte_service._recopilar_datos_reporte(request)
|
|
return {
|
|
"preview": True,
|
|
"tipo": request.tipo,
|
|
"registros": len(datos.get("datos", [])) if isinstance(datos, dict) else 0,
|
|
"datos_muestra": datos[:10] if isinstance(datos, list) else datos,
|
|
}
|
|
|
|
|
|
@router.get("/programados")
|
|
async def listar_reportes_programados(
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: Usuario = Depends(get_current_user),
|
|
):
|
|
"""Lista los reportes programados."""
|
|
# Por ahora retorna lista vacía, la funcionalidad completa requiere tabla de reportes programados
|
|
return {"items": [], "total": 0}
|
|
|
|
|
|
@router.post("/programar")
|
|
async def programar_reporte(
|
|
data: dict,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: Usuario = Depends(get_current_user),
|
|
):
|
|
"""Programa un nuevo reporte."""
|
|
# Por ahora solo retorna confirmación, la funcionalidad completa requiere tabla de reportes programados
|
|
return {
|
|
"message": "Reporte programado",
|
|
"tipo": data.get("tipo"),
|
|
"frecuencia": data.get("frecuencia"),
|
|
"email_destino": data.get("email_destino"),
|
|
}
|
|
|
|
|
|
@router.get("/dashboard", response_model=DashboardResumen)
|
|
async def obtener_dashboard(
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: Usuario = Depends(get_current_user),
|
|
):
|
|
"""
|
|
Obtiene datos del dashboard principal.
|
|
|
|
Returns:
|
|
Resumen del dashboard.
|
|
"""
|
|
reporte_service = ReporteService(db)
|
|
return await reporte_service.obtener_dashboard_resumen()
|
|
|
|
|
|
@router.get("/dashboard/graficos", response_model=DashboardGrafico)
|
|
async def obtener_graficos_dashboard(
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: Usuario = Depends(get_current_user),
|
|
):
|
|
"""
|
|
Obtiene datos para gráficos del dashboard.
|
|
|
|
Returns:
|
|
Datos para gráficos.
|
|
"""
|
|
reporte_service = ReporteService(db)
|
|
return await reporte_service.obtener_dashboard_graficos()
|
|
|
|
|
|
@router.post("/generar", response_model=ReporteResponse)
|
|
async def generar_reporte(
|
|
request: ReporteRequest,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: Usuario = Depends(get_current_user),
|
|
):
|
|
"""
|
|
Genera un reporte según los parámetros.
|
|
|
|
Args:
|
|
request: Parámetros del reporte.
|
|
|
|
Returns:
|
|
Información del reporte generado.
|
|
"""
|
|
reporte_service = ReporteService(db)
|
|
return await reporte_service.generar_reporte(request)
|
|
|
|
|
|
@router.get("/viajes")
|
|
async def reporte_viajes(
|
|
desde: datetime,
|
|
hasta: datetime,
|
|
vehiculo_id: Optional[int] = None,
|
|
formato: str = "json",
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: Usuario = Depends(get_current_user),
|
|
):
|
|
"""
|
|
Genera reporte de viajes.
|
|
|
|
Args:
|
|
desde: Fecha inicio.
|
|
hasta: Fecha fin.
|
|
vehiculo_id: Filtrar por vehículo.
|
|
formato: Formato de salida.
|
|
|
|
Returns:
|
|
Datos del reporte.
|
|
"""
|
|
reporte_service = ReporteService(db)
|
|
request = ReporteRequest(
|
|
tipo="viajes",
|
|
formato=formato if formato != "json" else "pdf",
|
|
fecha_inicio=desde,
|
|
fecha_fin=hasta,
|
|
vehiculos_ids=[vehiculo_id] if vehiculo_id else None,
|
|
)
|
|
|
|
datos = await reporte_service._recopilar_datos_reporte(request)
|
|
|
|
if formato == "json":
|
|
return datos
|
|
|
|
resultado = await reporte_service.generar_reporte(request)
|
|
return resultado
|
|
|
|
|
|
@router.get("/alertas")
|
|
async def reporte_alertas(
|
|
desde: datetime,
|
|
hasta: datetime,
|
|
vehiculo_id: Optional[int] = None,
|
|
formato: str = "json",
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: Usuario = Depends(get_current_user),
|
|
):
|
|
"""
|
|
Genera reporte de alertas.
|
|
|
|
Args:
|
|
desde: Fecha inicio.
|
|
hasta: Fecha fin.
|
|
vehiculo_id: Filtrar por vehículo.
|
|
formato: Formato de salida.
|
|
|
|
Returns:
|
|
Datos del reporte.
|
|
"""
|
|
reporte_service = ReporteService(db)
|
|
request = ReporteRequest(
|
|
tipo="alertas",
|
|
formato=formato if formato != "json" else "pdf",
|
|
fecha_inicio=desde,
|
|
fecha_fin=hasta,
|
|
vehiculos_ids=[vehiculo_id] if vehiculo_id else None,
|
|
)
|
|
|
|
datos = await reporte_service._recopilar_datos_reporte(request)
|
|
|
|
if formato == "json":
|
|
return datos
|
|
|
|
resultado = await reporte_service.generar_reporte(request)
|
|
return resultado
|
|
|
|
|
|
@router.get("/combustible")
|
|
async def reporte_combustible(
|
|
desde: datetime,
|
|
hasta: datetime,
|
|
vehiculo_id: Optional[int] = None,
|
|
formato: str = "json",
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: Usuario = Depends(get_current_user),
|
|
):
|
|
"""
|
|
Genera reporte de combustible.
|
|
|
|
Args:
|
|
desde: Fecha inicio.
|
|
hasta: Fecha fin.
|
|
vehiculo_id: Filtrar por vehículo.
|
|
formato: Formato de salida.
|
|
|
|
Returns:
|
|
Datos del reporte.
|
|
"""
|
|
reporte_service = ReporteService(db)
|
|
request = ReporteRequest(
|
|
tipo="combustible",
|
|
formato=formato if formato != "json" else "pdf",
|
|
fecha_inicio=desde,
|
|
fecha_fin=hasta,
|
|
vehiculos_ids=[vehiculo_id] if vehiculo_id else None,
|
|
)
|
|
|
|
datos = await reporte_service._recopilar_datos_reporte(request)
|
|
|
|
if formato == "json":
|
|
return datos
|
|
|
|
resultado = await reporte_service.generar_reporte(request)
|
|
return resultado
|
|
|
|
|
|
@router.get("/mantenimiento")
|
|
async def reporte_mantenimiento(
|
|
desde: datetime,
|
|
hasta: datetime,
|
|
vehiculo_id: Optional[int] = None,
|
|
formato: str = "json",
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: Usuario = Depends(get_current_user),
|
|
):
|
|
"""
|
|
Genera reporte de mantenimiento.
|
|
|
|
Args:
|
|
desde: Fecha inicio.
|
|
hasta: Fecha fin.
|
|
vehiculo_id: Filtrar por vehículo.
|
|
formato: Formato de salida.
|
|
|
|
Returns:
|
|
Datos del reporte.
|
|
"""
|
|
reporte_service = ReporteService(db)
|
|
request = ReporteRequest(
|
|
tipo="mantenimiento",
|
|
formato=formato if formato != "json" else "pdf",
|
|
fecha_inicio=desde,
|
|
fecha_fin=hasta,
|
|
vehiculos_ids=[vehiculo_id] if vehiculo_id else None,
|
|
)
|
|
|
|
datos = await reporte_service._recopilar_datos_reporte(request)
|
|
|
|
if formato == "json":
|
|
return datos
|
|
|
|
resultado = await reporte_service.generar_reporte(request)
|
|
return resultado
|