Files
ATLAS/backend/app/api/v1/combustible.py
ATLAS Admin e59aa2a742 feat: Complete ATLAS system installation and API fixes
## 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>
2026-01-25 03:04:23 +00:00

139 lines
4.3 KiB
Python

"""
Endpoints para gestión de combustible.
"""
from typing import List, Optional
from datetime import datetime
from fastapi import APIRouter, Depends, Query
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from app.core.database import get_db
from app.core.security import get_current_user
from app.models.usuario import Usuario
from app.models.carga_combustible import CargaCombustible
router = APIRouter(prefix="/combustible", tags=["Combustible"])
@router.get("")
async def listar_cargas(
vehiculo_id: Optional[int] = None,
vehiculoId: Optional[int] = None,
desde: Optional[datetime] = None,
hasta: Optional[datetime] = None,
skip: int = Query(0, ge=0),
limit: int = Query(50, ge=1, le=100),
pageSize: int = Query(None, ge=1, le=100),
db: AsyncSession = Depends(get_db),
current_user: Usuario = Depends(get_current_user),
):
"""Lista las cargas de combustible."""
# Handle both vehiculo_id and vehiculoId params
vid = vehiculo_id or vehiculoId
actual_limit = pageSize or limit
query = select(CargaCombustible).options(selectinload(CargaCombustible.vehiculo))
if vid:
query = query.where(CargaCombustible.vehiculo_id == vid)
if desde:
query = query.where(CargaCombustible.fecha >= desde)
if hasta:
query = query.where(CargaCombustible.fecha <= hasta)
query = query.offset(skip).limit(actual_limit).order_by(CargaCombustible.fecha.desc())
result = await db.execute(query)
cargas = result.scalars().all()
return {
"items": [
{
"id": c.id,
"vehiculoId": c.vehiculo_id,
"vehiculo_id": c.vehiculo_id,
"vehiculo": {
"id": c.vehiculo.id,
"nombre": c.vehiculo.nombre,
"placa": c.vehiculo.placa,
} if c.vehiculo else None,
"fecha": c.fecha,
"litros": c.litros,
"costo": c.total or 0,
"costo_total": c.total or 0,
"precioLitro": c.precio_litro or 0,
"odometro": c.odometro,
"tipo": c.tipo_combustible or "gasolina",
"tipo_combustible": c.tipo_combustible,
"gasolinera": c.estacion,
"estacion": c.estacion,
"rendimiento": None, # Calculated separately
"lleno": c.tanque_lleno,
}
for c in cargas
],
"total": len(cargas),
"page": skip // actual_limit + 1,
"pageSize": actual_limit,
}
@router.get("/stats")
async def obtener_estadisticas(
vehiculo_id: Optional[int] = None,
periodo: str = "mes",
db: AsyncSession = Depends(get_db),
current_user: Usuario = Depends(get_current_user),
):
"""Obtiene estadísticas de combustible."""
return {
"totalLitros": 0,
"costoTotal": 0,
"rendimientoPromedio": 0,
"cargas": 0,
}
@router.get("/{carga_id}")
async def obtener_carga(
carga_id: int,
db: AsyncSession = Depends(get_db),
current_user: Usuario = Depends(get_current_user),
):
"""Obtiene una carga de combustible por ID."""
result = await db.execute(
select(CargaCombustible)
.options(selectinload(CargaCombustible.vehiculo))
.where(CargaCombustible.id == carga_id)
)
carga = result.scalar_one_or_none()
if not carga:
return {"detail": "Carga no encontrada"}
return {
"id": carga.id,
"vehiculoId": carga.vehiculo_id,
"vehiculo_id": carga.vehiculo_id,
"vehiculo": {
"id": carga.vehiculo.id,
"nombre": carga.vehiculo.nombre,
"placa": carga.vehiculo.placa,
} if carga.vehiculo else None,
"fecha": carga.fecha,
"litros": carga.litros,
"costo": carga.total or 0,
"costo_total": carga.total or 0,
"precioLitro": carga.precio_litro or 0,
"odometro": carga.odometro,
"tipo": carga.tipo_combustible or "gasolina",
"tipo_combustible": carga.tipo_combustible,
"gasolinera": carga.estacion,
"estacion": carga.estacion,
"rendimiento": None,
"lleno": carga.tanque_lleno,
}