pr0nstar

VIII

......@@ -41,7 +41,9 @@ app = FastAPI(
root_path='/api'
)
app.include_router(project.router)
app.include_router(entity.router)
app.include_router(entity.router_entidad)
app.include_router(entity.router_ubigeo)
app.include_router(entity.router_da)
app.include_router(classifier.router_objeto)
app.include_router(classifier.router_acteco)
app.include_router(classifier.router_finfun)
......
......@@ -8,13 +8,16 @@ from sqlalchemy.orm import relationship as relationship_
SQLALCHEMY_DATABASE_URL = open('./docs/postgres').read().strip()
engine = create_engine(SQLALCHEMY_DATABASE_URL)
engine = create_engine(
SQLALCHEMY_DATABASE_URL,
pool_size=10,
max_overflow=5,
)
SessionLocal = sessionmaker(
autocommit=False,
autoflush=False,
bind=engine,
# pool_size=1,
#max_overflow=5
)
Base = declarative_base()
......@@ -49,3 +52,7 @@ def update_from_schema(model, schema):
for field, field_data in schema.dict().items():
setattr(model, field, field_data)
return model
def model_columns(model):
return [col.label(col.key) for col in model.__table__.c]
......
......@@ -101,7 +101,7 @@ class ClasGeografico(ClasBase, Base):
ubigeo: Mapped[str] = mapped_column(Text, primary_key=True)
desc_departamento: Mapped[str] = mapped_column(String(12))
desc_departamento: Mapped[str] = mapped_column(String(18))
desc_ubigeo: Mapped[str | None] = mapped_column(Text)
municipio_ubigeo: Mapped[int | None] = mapped_column(Integer)
......
......@@ -44,7 +44,7 @@ class EjecucionClasificadores(Base):
devengado: Mapped[float] = mapped_column(Numeric(30, 15))
padre: Mapped[str] = mapped_column(Text)
hijo: Mapped[str] = mapped_column(Text)
hijo: Mapped[str | None] = mapped_column(Text)
class EjecucionEntidades(Base):
......@@ -90,7 +90,9 @@ class Timeline(Base):
class TimeSeries(Base):
__tablename__ = "diario_timeseries"
__table_args__ = (
{"schema": "web"},
)
id: Mapped[int] = mapped_column(Integer, primary_key=True)
fecha: Mapped[date] = mapped_column(Date)
......
from sqlalchemy.orm import Mapped, mapped_column
from presupuestov1.model import Base
from presupuestov1.model import Base, model_columns
from sqlalchemy import (
Integer,
......@@ -9,7 +9,7 @@ from sqlalchemy import (
Index,
MetaData,
)
from sqlalchemy import and_, or_
from sqlalchemy import and_, or_, select
class TreemapObjeto(Base):
......@@ -115,4 +115,6 @@ def get_clas_entities(query_filters, db, query, ClassObject, object_id):
ids = or_([getattr(ClassObject, object_id) == _ for _ in ids])
query_filters.append(ids)
return db.query(ClassObject).filter(and_(*query_filters)).all()
return db.execute(
select(*model_columns(ClassObject)).where(and_(*query_filters))
).mappings().all()
......
......@@ -4,7 +4,7 @@ from typing import List, Any, Optional, Union
from fastapi import APIRouter, Depends, Request, HTTPException, Body
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_
from sqlalchemy import and_, or_, select
from presupuestov1 import model, schema, constant, schemas, models, search
......@@ -26,10 +26,6 @@ router_finfun = APIRouter(
tags=['finfun'],
)
router_ubigeo = APIRouter(
prefix='/ubigeo',
tags=['ubigeo'],
)
###############################################################################
......@@ -51,11 +47,6 @@ def fetch_object_classifier(db: Session = Depends(model.get_db)):
return _fetch_classifier('finfun', db)
@router_ubigeo.get('/clasificador', response_model=List[schemas.classifier.ClasGeografico])
def fetch_object_classifier(db: Session = Depends(model.get_db)):
return _fetch_classifier('ubigeo', db)
@router_objeto.get('/{object_id}', response_model=schemas.objeto.ClasObjetosEstados)
def fetch_objeto_estado(
object_id: str,
......@@ -84,13 +75,15 @@ def fetch_objeto_entidad(
gestion = query.gestion or 0
ClasObjetos = models.objeto.ObjetoEntidad
return db.query(ClasObjetos).filter(
ClasObjetos.objeto == object_id,
ClasObjetos.gestion == gestion
).all()
return db.execute(
select(*model.model_columns(ClasObjetos)).where(
ClasObjetos.objeto == object_id,
ClasObjetos.gestion == gestion
)
).mappings().all()
@router_objeto.get('/{object_id}/entidades/map', response_model=List[schemas.treemap.TreemapObjeto])
@router_objeto.get('/{object_id}/entidades/map', response_model=List[schemas.treemap.TreemapObjetoSingle])
def fetch_objeto_treemap(
object_id: str,
db: Session = Depends(model.get_db),
......@@ -119,11 +112,11 @@ def fetch_objeto_entidad_single(
@router_acteco.get('/{acteco_id}', response_model=schemas.acteco.ClasActecoEstados)
def fetch_objeto_estado(
def fetch_acteco_estado(
acteco_id: str,
db: Session = Depends(model.get_db),
):
ClasEstado = models.objeto.ActecoEstado
ClasEstado = models.acteco.ActecoEstado
estados = db.query(ClasEstado).filter(
ClasEstado.acteco == acteco_id,
).all()
......@@ -146,13 +139,15 @@ def fetch_acteco_entidad(
gestion = query.gestion or 0
ClasObjetos = models.acteco.ActecoEntidad
return db.query(ClasObjetos).filter(
ClasObjetos.acteco == acteco_id,
ClasObjetos.gestion == gestion
).all()
return db.execute(
select(*model.model_columns(ClasObjetos)).where(
ClasObjetos.acteco == acteco_id,
ClasObjetos.gestion == gestion
)
).mappings().all()
@router_acteco.get('/{acteco_id}/entidades/map', response_model=List[schemas.treemap.TreemapActeco])
@router_acteco.get('/{acteco_id}/entidades/map', response_model=List[schemas.treemap.TreemapActecoSingle])
def fetch_acteco_treemap(
acteco_id: str,
db: Session = Depends(model.get_db),
......@@ -209,13 +204,15 @@ def fetch_finfun_entidad(
gestion = query.gestion or 0
ClasObjetos = models.finfun.FinfunEntidad
return db.query(ClasObjetos).filter(
ClasObjetos.finfun == finfun_id,
ClasObjetos.gestion == gestion
).all()
return db.execute(
select(*model.model_columns(ClasObjetos)).where(
ClasObjetos.finfun == finfun_id,
ClasObjetos.gestion == gestion
)
).mappings().all()
@router_finfun.get('/{finfun_id}/entidades/map', response_model=List[schemas.treemap.TreemapFinFun])
@router_finfun.get('/{finfun_id}/entidades/map', response_model=List[schemas.treemap.TreemapFinFunSingle])
def fetch_finfun_treemap(
finfun_id: str,
db: Session = Depends(model.get_db),
......@@ -228,6 +225,7 @@ def fetch_finfun_treemap(
], db, query, Treemap, 'entidad'
)
@router_finfun.get('/{finfun_id}/entidades/{entidad_id}', response_model=List[schemas.finfun.FinfunEntidad])
def fetch_finfun_entidad_single(
finfun_id: str,
......@@ -242,15 +240,16 @@ def fetch_finfun_entidad_single(
ClasObjetos.entidad == entidad_id
).all()
###############################################################################
# priv
###############################################################################
def _fetch_classifier(clas, db):
ClassObject = {
ClasObject = {
'objeto': models.classifier.ClasObjetos,
'acteco': models.classifier.ClasActeco,
'finfun': models.classifier.ClasFinfun,
'ubigeo': models.classifier.ClasGeografico,
}[clas]
return db.query(ClassObject).all()
return db.query(ClasObject).all()
......
......@@ -40,7 +40,7 @@ def fetch_clasificadores(
if query.dias is not None:
filters.append(Daily.dias == query.dias)
return db.query(Daily).filter(*filters).all()
return db.query(Daily).filter(*filters).order_by(Daily.devengado.desc()).all()
@router.get('/entidades', response_model=List[schemas.daily.EjecucionEntidades])
......@@ -61,7 +61,7 @@ def fetch_entidades(
if query.entidad is not None:
filters.append(Daily.entidad == query.entidad)
return db.query(Daily).filter(*filters).offset(
return db.query(Daily).filter(*filters).order_by(Daily.devengado.desc()).offset(
(page - 1) * page_size
).limit(page_size).all()
......
......@@ -2,9 +2,9 @@ import time
from typing import List, Any, Optional, Union
from fastapi import APIRouter, Depends, Request, HTTPException, Body
from fastapi import APIRouter, Depends, Request, HTTPException, Body, Response
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_
from sqlalchemy import and_, or_, select
from presupuestov1 import model, schema, constant, schemas, models, search
......@@ -43,11 +43,12 @@ def fetch_classifier(
return db.query(models.classifier.ClasGeografico).all()
# base
@router_entidad.get('/{entity_id:str}', response_model=schemas.entity.ClasInstitucionalIngresosGastos)
def fetch_entity(
entity_id: int,
entity_id: str,
db: Session = Depends(model.get_db),
):
ClasInstitucional = models.classifier.ClasInstitucional
......@@ -55,7 +56,7 @@ def fetch_entity(
ClasInstitucional.entidad == entity_id
).one()
gastos_ingresos = get_resumen('entidad', entity_id)
gastos_ingresos = get_resumen(db, 'entidad', entity_id)
setattr(entidad, 'gastos_ingresos', gastos_ingresos)
return entidad
......@@ -63,7 +64,7 @@ def fetch_entity(
@router_ubigeo.get('/{ubigeo_id:str}', response_model=schemas.entity.ClasGeograficoIngresosGastos)
def fetch_entity(
ubigeo_id: int,
ubigeo_id: str,
db: Session = Depends(model.get_db),
):
ClasGeografico = models.classifier.ClasGeografico
......@@ -71,7 +72,7 @@ def fetch_entity(
ClasGeografico.ubigeo == ubigeo_id
).one()
gastos_ingresos = get_resumen('municipio_ubigeo', ubigeo_id)
gastos_ingresos = get_resumen(db, 'municipio_ubigeo', ubigeo_id)
setattr(ubigeo, 'gastos_ingresos', gastos_ingresos)
return ubigeo
......@@ -81,81 +82,94 @@ def fetch_entity(
@router_entidad.get('/{entity_id:str}/objetos', response_model=List[schemas.entity.EntidadDistribucion])
def fetch_entity_objetos(
entity_id: int,
entity_id: str,
db: Session = Depends(model.get_db),
query: schema.QueryParams = Depends(),
):
return get_distribuciones('entidad', entidad_id, 'objeto', query)
return get_distribuciones(db, 'entidad', entity_id, 'objeto', query)
@router_ubigeo.get('/{ubigeo_id:str}/objetos', response_model=List[schemas.entity.EntidadDistribucion])
def fetch_entity_objetos(
ubigeo_id: int,
ubigeo_id: str,
db: Session = Depends(model.get_db),
query: schema.QueryParams = Depends(),
):
return get_distribuciones('municipio_ubigeo', ubigeo_id, 'objeto', query)
return get_distribuciones(db, 'municipio_ubigeo', ubigeo_id, 'objeto', query)
@router_entidad.get('/{entity_id:str}/finfuns', response_model=List[schemas.entity.EntidadDistribucion])
def fetch_entity_finfuns(
entity_id: int,
entity_id: str,
db: Session = Depends(model.get_db),
query: schema.QueryParams = Depends(),
):
return get_distribuciones('entidad', entidad_id, 'finfun', query)
return get_distribuciones(db, 'entidad', entity_id, 'finfun', query)
@router_ubigeo.get('/{ubigeo_id:str}/finfuns', response_model=List[schemas.entity.EntidadDistribucion])
def fetch_entity_finfuns(
ubigeo_id: int,
ubigeo_id: str,
db: Session = Depends(model.get_db),
query: schema.QueryParams = Depends(),
):
return get_distribuciones('municipio_ubigeo', ubigeo_id, 'finfun', query)
return get_distribuciones(db, 'municipio_ubigeo', ubigeo_id, 'finfun', query)
@router_entidad.get('/{entity_id:str}/actecos', response_model=List[schemas.entity.EntidadDistribucion])
def fetch_entity_actecos(
entity_id: int,
entity_id: str,
db: Session = Depends(model.get_db),
query: schema.QueryParams = Depends(),
):
return get_distribuciones('entidad', entidad_id, 'acteco', query)
return get_distribuciones(db, 'entidad', entity_id, 'acteco', query)
@router_ubigeo.get('/{ubigeo_id:str}/actecos', response_model=List[schemas.entity.EntidadDistribucion])
def fetch_entity_actecos(
ubigeo_id: int,
ubigeo_id: str,
db: Session = Depends(model.get_db),
query: schema.QueryParams = Depends(),
):
return get_distribuciones('municipio_ubigeo', ubigeo_id, 'acteco', query)
return get_distribuciones(db, 'municipio_ubigeo', ubigeo_id, 'acteco', query)
###############################################################################
# private
###############################################################################
def get_distribuciones(tipo_codigo, entidad_id, dimension, query):
def get_distribuciones(db, tipo_codigo, entity_id, dimension, query):
EntidadDistribucionesSchema = schemas.entity.EntidadDistribucion
EntidadDistribuciones = models.entity.EntidadDistribuciones
schema_fields = EntidadDistribucionesSchema.model_fields.keys()
cols = [getattr(EntidadDistribuciones, name) for name in schema_fields]
filters = []
if query.gestion is not None:
filters.append(EntidadDistribuciones.gestion == query.gestion)
filters.extend(
filters.extend([
EntidadDistribuciones.tipo_codigo == tipo_codigo,
EntidadDistribuciones.codigo == entity_id,
EntidadDistribuciones.dimension == dimension,
)
])
return db.query(EntidadDistribuciones).filter(*filters).all()
return db.execute(
select(*cols).where(*filters)
).mappings().all()
def get_resumen(tipo_codigo, codigo):
def get_resumen(db, tipo_codigo, codigo):
EntidadResumenes = models.entity.EntidadResumenes
return db.query(EntidadResumenes).filter(
EntidadResumenes.tipo_codigo == tipo_codigo,
EntidadResumenes.codigo == codigo,
EntidadResumenSchema = schemas.entity.EntidadResumen
schema_fields = EntidadResumenSchema.model_fields.keys()
cols = [getattr(EntidadResumenes, name) for name in schema_fields]
return db.execute(
select(*cols).where(
EntidadResumenes.tipo_codigo == tipo_codigo,
EntidadResumenes.codigo == codigo,
)
).all()
......
......@@ -17,7 +17,8 @@ class SearchQueryParams(BaseModel):
class QueryParams(BaseModel):
id: Optional[str] = Query(default=None)
gestion: Optional[int] = Query(default=0)
gestion: Optional[int] = Query(default=None)
nivel: Optional[str] = Query(default=None)
class DailyParams(BaseModel):
transferencias: Optional[bool] = Query(default=False)
......
......@@ -34,7 +34,6 @@ class ActecoEntidad(OrmBaseModel):
acteco: str
entidad: int
nivel: str | None
entidad_desc: str | None
monto: float | None
per_capita: float | None
ranking: int | None
......
......@@ -29,11 +29,16 @@ class ClasInstitucional(OrmBaseModel):
n_gestiones: int | None
def get_clasdesc(name):
return create_model(
'_ClasDesc{}'.format(name),
**{'gestion': str, 'desc_{}'.format(name): str},
)
# def get_clasdesc(name):
# return create_model(
# '_ClasDesc{}'.format(name),
# **{'gestion': str, 'desc_{}'.format(name): str},
# )
class _ClasDesc(OrmBaseModel):
gestion: str
descripcion: str | None
class ClasBase(OrmBaseModel):
nivel: str | None
......@@ -45,19 +50,19 @@ class ClasBase(OrmBaseModel):
class ClasObjetos(ClasBase):
objeto: str
desc_objeto: str | None
descripciones: list[get_clasdesc('objeto')] | None
descripciones: list[_ClasDesc] | None
class ClasFinfun(ClasBase):
finfun: str
desc_finfun: str | None
descripciones: list[get_clasdesc('finfun')] | None
descripciones: list[_ClasDesc] | None
class ClasActeco(ClasBase):
acteco: str
desc_acteco: str | None
descripciones: list[get_clasdesc('acteco')] | None
descripciones: list[_ClasDesc] | None
class ClasGeografico(ClasBase):
......@@ -65,7 +70,7 @@ class ClasGeografico(ClasBase):
desc_ubigeo: str | None
desc_departamento: str | None
municipio_ubigeo: int | None
descripciones: list[get_clasdesc('ubigeo')] | None
descripciones: list[_ClasDesc] | None
# Ingresos
......@@ -90,7 +95,7 @@ class ClasOrganismos(OrmBaseModel):
class ClasRubros(ClasBase):
rubro: str
desc_rubro: str | None
descripciones: list[get_clasdesc('rubro')] | None
descripciones: list[_ClasDesc] | None
class ClasFuentes(ClasBase):
......@@ -98,4 +103,4 @@ class ClasFuentes(ClasBase):
desc_fuente: str | None
grupo_fuente: str
desc_grupo_fuente: str | None
descripciones: list[get_clasdesc('fuente')] | None
descripciones: list[_ClasDesc] | None
......
......@@ -6,9 +6,6 @@ from presupuestov1 import schemas
class EntidadDistribucion(OrmBaseModel):
tipo: str
tipo_codigo: str
codigo: str
dimension: str
gestion: int
padre: str
hijo: str
......@@ -19,13 +16,9 @@ class EntidadDistribucion(OrmBaseModel):
class EntidadResumen(OrmBaseModel):
tipo: str
tipo_codigo: str
codigo: str
gestion: int
devengado: float
ranking: int | None
desc: str | None
desc_padre: str | None
class ClasInstitucionalIngresosGastos(schemas.classifier.ClasInstitucional):
......
......@@ -41,7 +41,6 @@ class FinfunEntidad(OrmBaseModel):
finfun: str
entidad: int
nivel: str | None
entidad_desc: str | None
monto: float | None
per_capita: float | None
ranking: int | None
......
......@@ -41,7 +41,6 @@ class ObjetoEntidad(OrmBaseModel):
objeto: str
entidad: int
nivel: str | None
entidad_desc: str | None
monto: float | None
per_capita: float | None
ranking: int | None
......
......@@ -23,6 +23,11 @@ class TreemapObjeto(Treemap):
desc_objeto: str | None
desc_entidad: str | None
class TreemapObjetoSingle(Treemap):
objeto: int
parent: int | None
desc_entidad: str | None
class TreemapFinFun(Treemap):
finfun: str
......@@ -31,8 +36,20 @@ class TreemapFinFun(Treemap):
desc_entidad: str | None
class TreemapFinFunSingle(Treemap):
finfun: str
parent: str | None
desc_entidad: str | None
class TreemapActeco(Treemap):
acteco: str
parent: str | None
desc_acteco: str | None
desc_entidad: str | None
class TreemapActecoSingle(Treemap):
acteco: str
parent: str | None
desc_entidad: str | None
......