daily.py 4.26 KB
from typing import List

from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session, aliased
from sqlalchemy import func

from presupuestov1 import model, schema, schemas, models
from presupuestov1.routers._decorators import not_found


router = APIRouter(
	prefix='/diario',
	tags=['diario'],
)


###############################################################################
# GET
###############################################################################

@router.get('/status', response_model=schemas.daily.UpdateStatus)
@not_found
def fetch_status(
	db: Session = Depends(model.get_db),
):
	Daily = models.daily.UpdateStatus
	return db.query(Daily).order_by(
		Daily.fecha_actualizacion.desc()
	).first()


@router.get('/clasificadores', response_model=List[schemas.daily.EjecucionClasificadores])
@not_found
def fetch_clasificadores(
	db: Session = Depends(model.get_db),
	query: schema.DailyParams = Depends(),
):
	Daily = models.daily.EjecucionClasificadores

	filters = []
	if query.transferencias is not None:
		filters.append(Daily.transferencias == query.transferencias)
	if query.dias is not None:
		filters.append(Daily.dias == query.dias)

	return db.query(Daily).filter(*filters).order_by(Daily.devengado.desc()).all()


@router.get('/entidades', response_model=List[schemas.daily.EjecucionEntidades])
@not_found
def fetch_entidades(
	db: Session = Depends(model.get_db),
	query: schema.DailyParams = Depends(),
):
	Daily = models.daily.EjecucionEntidades
	transferencias = query.transferencias or False # :O
	page = query.page or 1
	page_size = 10

	filters = []
	if not transferencias:
		filters.append(Daily.transferencias == query.transferencias)
	if query.dias is not None:
		filters.append(Daily.dias == query.dias)
	if query.entidad is not None:
		filters.append(Daily.entidad == query.entidad)

	return db.query(Daily).filter(*filters).order_by(Daily.devengado.desc()).offset(
		(page - 1) * page_size
	).limit(page_size).all()


@router.get('/timeline', response_model=List[schemas.daily.Timeline])
@not_found
def fetch_timeline(
    db: Session = Depends(model.get_db),
    query: schema.DailyParams = Depends(),
):
    Daily = models.daily.Timeline
    page = query.page or 1
    page_size = 10

    if query.entidad is not None:
        stmt = (
            select(Daily)
            .where(Daily.entidad == query.entidad)
            .order_by(Daily.devengado.desc(), Daily.id)
            .offset((page - 1) * page_size)
            .limit(page_size)
        )
        return db.execute(stmt).scalars().all()

    total_devengado = func.sum(Daily.devengado).label("total_devengado")

    top_entities = (
        select(
            Daily.entidad.label("entidad"),
            total_devengado,
        )
        .group_by(Daily.entidad)
        .order_by(total_devengado.desc(), Daily.entidad)
        .limit(10)
        .subquery()
    )

    ranked = (
        select(
            Daily.entidad.label("entidad"),
            Daily.devengado.label("devengado"),
            Daily.entidad_desc_area.label("entidad_desc_area"),
            Daily.entidad_desc_entidad.label("entidad_desc_entidad"),
            Daily.desc_programa.label("desc_programa"),
            Daily.desc_actividad_proyecto.label("desc_actividad_proyecto"),
            Daily.id.label("id"),
            top_entities.c.total_devengado,
            func.row_number().over(
                partition_by=Daily.entidad,
                order_by=(Daily.devengado.desc(), Daily.id),
            ).label("row_num"),
        )
        .join(top_entities, top_entities.c.entidad == Daily.entidad)
        .subquery()
    )

    stmt = (
        select(
            ranked.c.entidad,
            ranked.c.devengado,
            ranked.c.entidad_desc_area,
            ranked.c.entidad_desc_entidad,
            ranked.c.desc_programa,
            ranked.c.desc_actividad_proyecto,
        )
        .where(ranked.c.row_num <= page_size)
        .order_by(
            ranked.c.total_devengado.desc(),
            ranked.c.entidad,
            ranked.c.devengado.desc(),
            ranked.c.id,
        )
    )

    return db.execute(stmt).mappings().all()


@router.get('/timeseries', response_model=List[schemas.daily.TimeSeries])
@not_found
def fetch_timeseries(
	db: Session = Depends(model.get_db),
):
	return db.query(models.daily.TimeSeries).all()