Showing
16 changed files
with
639 additions
and
0 deletions
.gitignore
0 → 100644
constant.py
0 → 100644
File mode changed
main.py
0 → 100644
| 1 | +import logging | ||
| 2 | + | ||
| 3 | +from typing import Any, Union | ||
| 4 | + | ||
| 5 | +from fastapi import FastAPI | ||
| 6 | +from fastapi.middleware import Middleware | ||
| 7 | +from starlette.responses import JSONResponse | ||
| 8 | +from starlette.requests import HTTPConnection, Request | ||
| 9 | + | ||
| 10 | +from starlette_context import context, plugins | ||
| 11 | +from starlette_context.middleware import RawContextMiddleware | ||
| 12 | + | ||
| 13 | +from aiocache import caches | ||
| 14 | + | ||
| 15 | +from presupuestov1.routers import ( | ||
| 16 | + project | ||
| 17 | +) | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +logging.basicConfig( | ||
| 21 | + level=logging.INFO, | ||
| 22 | + format='%(asctime)s %(message)s', | ||
| 23 | + filename='log.log', | ||
| 24 | +) | ||
| 25 | +logging.getLogger('api_proy2').setLevel(logging.DEBUG) | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +app = FastAPI( | ||
| 29 | + title='Jorvi API', | ||
| 30 | + middleware=[ | ||
| 31 | + Middleware( | ||
| 32 | + RawContextMiddleware, | ||
| 33 | + plugins=( | ||
| 34 | + plugins.RequestIdPlugin(), | ||
| 35 | + ) | ||
| 36 | + ) | ||
| 37 | + ], | ||
| 38 | + root_path='/api' | ||
| 39 | +) | ||
| 40 | +app.include_router(project.router) | ||
| 41 | + | ||
| 42 | + | ||
| 43 | +@app.on_event('startup') | ||
| 44 | +async def startup_event(): | ||
| 45 | + caches.set_config({ | ||
| 46 | + 'default': { | ||
| 47 | + 'cache': 'aiocache.SimpleMemoryCache', | ||
| 48 | + 'serializer': { | ||
| 49 | + 'class': 'aiocache.serializers.StringSerializer' # Cache raw text | ||
| 50 | + } | ||
| 51 | + } | ||
| 52 | + }) | ||
| 53 | + | ||
| 54 | +@app.on_event('shutdown') | ||
| 55 | +async def shutdown_event(): | ||
| 56 | + default_cache = caches.get('default') | ||
| 57 | + if hasattr(default_cache, 'close'): | ||
| 58 | + await default_cache.close() |
model.py
0 → 100644
| 1 | +import contextlib | ||
| 2 | +import re | ||
| 3 | + | ||
| 4 | +from sqlalchemy import create_engine | ||
| 5 | +from sqlalchemy.ext.declarative import declarative_base | ||
| 6 | +from sqlalchemy.orm import sessionmaker | ||
| 7 | +from sqlalchemy.orm import relationship as relationship_ | ||
| 8 | + | ||
| 9 | +SQLALCHEMY_DATABASE_URL = open('./docs/postgres').read().strip() | ||
| 10 | + | ||
| 11 | +engine = create_engine(SQLALCHEMY_DATABASE_URL) | ||
| 12 | +SessionLocal = sessionmaker( | ||
| 13 | + autocommit=False, | ||
| 14 | + autoflush=False, | ||
| 15 | + bind=engine, | ||
| 16 | + # pool_size=1, | ||
| 17 | + #max_overflow=5 | ||
| 18 | +) | ||
| 19 | + | ||
| 20 | +Base = declarative_base() | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +def get_db(): | ||
| 24 | + try: | ||
| 25 | + db = SessionLocal() | ||
| 26 | + yield db | ||
| 27 | + finally: | ||
| 28 | + db.close() | ||
| 29 | + | ||
| 30 | + | ||
| 31 | +@contextlib.contextmanager | ||
| 32 | +def transaction(session): | ||
| 33 | + if not session.in_transaction(): | ||
| 34 | + with session.begin(): | ||
| 35 | + yield | ||
| 36 | + else: | ||
| 37 | + yield | ||
| 38 | + | ||
| 39 | + session.commit() | ||
| 40 | + | ||
| 41 | + | ||
| 42 | +def relationship(*args, **kwargs): | ||
| 43 | + if 'passive_deletes' not in kwargs and 'viewonly' not in kwargs: | ||
| 44 | + kwargs['passive_deletes'] = True | ||
| 45 | + return relationship_(*args, **kwargs) | ||
| 46 | + | ||
| 47 | + | ||
| 48 | +def update_from_schema(model, schema): | ||
| 49 | + for field, field_data in schema.dict().items(): | ||
| 50 | + setattr(model, field, field_data) | ||
| 51 | + return model |
models/__init__.py
0 → 100644
File mode changed
routers/__init__.py
0 → 100644
File mode changed
routers/project.py
0 → 100644
| 1 | +import time | ||
| 2 | + | ||
| 3 | +from typing import List, Any, Optional, Union | ||
| 4 | + | ||
| 5 | +from fastapi import APIRouter, Depends, Request, HTTPException, Body | ||
| 6 | +from sqlalchemy.orm import Session | ||
| 7 | + | ||
| 8 | +from presupuestov1 import model, schema, constant, schemas, models, search | ||
| 9 | + | ||
| 10 | +from aiocache import cached | ||
| 11 | + | ||
| 12 | + | ||
| 13 | +router = APIRouter( | ||
| 14 | + prefix='/proyecto', | ||
| 15 | + tags=['proyecto'], | ||
| 16 | +) | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +############################################################################### | ||
| 20 | +# GET | ||
| 21 | +############################################################################### | ||
| 22 | + | ||
| 23 | +# @router.get('/{project_id}', response_model=schemas.project.Project) | ||
| 24 | +# def fetch_branch( | ||
| 25 | +# project_id: int, | ||
| 26 | +# db: Session = Depends(model.get_db), | ||
| 27 | +# ): | ||
| 28 | +# return models.project.get_project(db, project_id) | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | +@router.get('/search', response_model=schemas.project.Search) | ||
| 33 | +def fetch_search( | ||
| 34 | + query: schema.QueryParams = Depends(), | ||
| 35 | +): | ||
| 36 | + if query.q is None or len(query.q) < 3: | ||
| 37 | + return [] | ||
| 38 | + | ||
| 39 | + return do_search(query.q, query.page) | ||
| 40 | + | ||
| 41 | + | ||
| 42 | +############################################################################### | ||
| 43 | +# GET | ||
| 44 | +############################################################################### | ||
| 45 | + | ||
| 46 | +# @cached(ttl=10) | ||
| 47 | +def do_search(query, page): | ||
| 48 | + return search.do_search(query, page) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
schema.py
0 → 100644
| 1 | +import re | ||
| 2 | + | ||
| 3 | +from typing import Optional | ||
| 4 | +from pydantic import BaseModel, ConfigDict, Field, root_validator | ||
| 5 | +from fastapi import Query | ||
| 6 | + | ||
| 7 | + | ||
| 8 | +class OrmBaseModel(BaseModel): | ||
| 9 | + model_config = ConfigDict(from_attributes=True) | ||
| 10 | + | ||
| 11 | + | ||
| 12 | +class QueryParams(BaseModel): | ||
| 13 | + page: Optional[int] = Query(default=1) | ||
| 14 | + q: Optional[str] = Query(default=None) |
schemas/__init__.py
0 → 100644
schemas/acteco.py
0 → 100644
| 1 | +from sqlalchemy.orm import Mapped, mapped_column | ||
| 2 | +from presupuestov1.schema import BaseModel | ||
| 3 | + | ||
| 4 | +from sqlalchemy import ( | ||
| 5 | + Integer, | ||
| 6 | + String, | ||
| 7 | + Text, | ||
| 8 | + Numeric, | ||
| 9 | + Index, | ||
| 10 | + MetaData, | ||
| 11 | +) | ||
| 12 | + | ||
| 13 | + | ||
| 14 | +class ActecoEstado(BaseModel): | ||
| 15 | + __tablename__ = "finfun_estado" | ||
| 16 | + __table_args__ = ( | ||
| 17 | + Index("idx_acteco_estado_acteco", "acteco"), | ||
| 18 | + Index("idx_acteco_estado_acteco_gestion", "acteco", "gestion"), | ||
| 19 | + ) | ||
| 20 | + | ||
| 21 | + gestion: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 22 | + acteco: Mapped[str] = mapped_column(Text, primary_key=True) | ||
| 23 | + | ||
| 24 | + total: Mapped[float | None] = mapped_column(Numeric) | ||
| 25 | + poblacion: Mapped[int | None] = mapped_column(Integer) | ||
| 26 | + n_entidades: Mapped[int | None] = mapped_column(Integer) | ||
| 27 | + per_capita: Mapped[float | None] = mapped_column(Numeric) | ||
| 28 | + total_gestion: Mapped[float | None] = mapped_column(Numeric) | ||
| 29 | + prop: Mapped[float | None] = mapped_column(Numeric) | ||
| 30 | + ranking: Mapped[int | None] = mapped_column(Integer) | ||
| 31 | + n_pares: Mapped[int | None] = mapped_column(Integer) | ||
| 32 | + | ||
| 33 | + top1_entidad: Mapped[int | None] = mapped_column(Integer) | ||
| 34 | + top1_entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 35 | + top1_monto: Mapped[float | None] = mapped_column(Numeric) | ||
| 36 | + top1_pct: Mapped[float | None] = mapped_column(Numeric) | ||
| 37 | + | ||
| 38 | + top2_entidad: Mapped[int | None] = mapped_column(Integer) | ||
| 39 | + top2_entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 40 | + top2_monto: Mapped[float | None] = mapped_column(Numeric) | ||
| 41 | + top2_pct: Mapped[float | None] = mapped_column(Numeric) | ||
| 42 | + | ||
| 43 | + top3_entidad: Mapped[int | None] = mapped_column(Integer) | ||
| 44 | + top3_entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 45 | + top3_monto: Mapped[float | None] = mapped_column(Numeric) | ||
| 46 | + top3_pct: Mapped[float | None] = mapped_column(Numeric) | ||
| 47 | + | ||
| 48 | + | ||
| 49 | +class ActecoEntidad(BaseModel): | ||
| 50 | + __tablename__ = "acteco_entidad" | ||
| 51 | + __table_args__ = ( | ||
| 52 | + Index("idx_finfun_entidad_acteco", "acteco"), | ||
| 53 | + Index("idx_finfun_entidad_acteco_entidad", "acteco", "entidad"), | ||
| 54 | + ) | ||
| 55 | + | ||
| 56 | + gestion: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 57 | + acteco: Mapped[str] = mapped_column(Text, primary_key=True) | ||
| 58 | + entidad: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 59 | + | ||
| 60 | + nivel: Mapped[str | None] = mapped_column(Text) | ||
| 61 | + entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 62 | + monto: Mapped[float | None] = mapped_column(Numeric) | ||
| 63 | + per_capita: Mapped[float | None] = mapped_column(Numeric) | ||
| 64 | + ranking: Mapped[int | None] = mapped_column(Integer) | ||
| 65 | + prop: Mapped[float | None] = mapped_column(Numeric) | ||
| 66 | + n_entidades: Mapped[int | None] = mapped_column(Integer) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
schemas/classifier.py
0 → 100644
| 1 | +from sqlalchemy.orm import Mapped, mapped_column | ||
| 2 | +from presupuestov1.schema import BaseModel | ||
| 3 | + | ||
| 4 | +from sqlalchemy import ( | ||
| 5 | + Integer, | ||
| 6 | + String, | ||
| 7 | + Text, | ||
| 8 | + Numeric, | ||
| 9 | + Index, | ||
| 10 | + MetaData, | ||
| 11 | +) | ||
| 12 | +from sqlalchemy.dialects.postgresql import JSONB | ||
| 13 | + | ||
| 14 | + | ||
| 15 | +class ClasInstitucional(BaseModel): | ||
| 16 | + __tablename__ = "clas_institucional" | ||
| 17 | + | ||
| 18 | + entidad: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 19 | + desc_entidad: Mapped[str | None] = mapped_column(Text) | ||
| 20 | + sigla_entidad: Mapped[str | None] = mapped_column(String(50)) | ||
| 21 | + | ||
| 22 | + sector: Mapped[str | None] = mapped_column(String(10)) | ||
| 23 | + desc_sector: Mapped[str | None] = mapped_column(Text) | ||
| 24 | + sigla_sector: Mapped[str | None] = mapped_column(String(20)) | ||
| 25 | + | ||
| 26 | + subsector: Mapped[str | None] = mapped_column(String(10)) | ||
| 27 | + desc_subsector: Mapped[str | None] = mapped_column(Text) | ||
| 28 | + sigla_subsector: Mapped[str | None] = mapped_column(String(20)) | ||
| 29 | + | ||
| 30 | + area: Mapped[str | None] = mapped_column(String(10)) | ||
| 31 | + desc_area: Mapped[str | None] = mapped_column(Text) | ||
| 32 | + sigla_area: Mapped[str | None] = mapped_column(String(20)) | ||
| 33 | + | ||
| 34 | + subarea: Mapped[str | None] = mapped_column(String(10)) | ||
| 35 | + desc_subarea: Mapped[str | None] = mapped_column(Text) | ||
| 36 | + sigla_subarea: Mapped[str | None] = mapped_column(String(20)) | ||
| 37 | + | ||
| 38 | + gestiones: Mapped[str | None] = mapped_column(Text) | ||
| 39 | + n_gestiones: Mapped[int | None] = mapped_column(Integer) | ||
| 40 | + | ||
| 41 | + | ||
| 42 | +class ClasObjetos(Base): | ||
| 43 | + __tablename__ = "clas_objetos" | ||
| 44 | + | ||
| 45 | + nivel: Mapped[str | None] = mapped_column(Text) | ||
| 46 | + objeto: Mapped[str] = mapped_column(Text, primary_key=True) | ||
| 47 | + desc_objeto: Mapped[str | None] = mapped_column(Text) | ||
| 48 | + | ||
| 49 | + gestiones: Mapped[str | None] = mapped_column(Text) | ||
| 50 | + n_gestiones: Mapped[int | None] = mapped_column(Integer) | ||
| 51 | + n_variaciones: Mapped[int | None] = mapped_column(Integer) | ||
| 52 | + | ||
| 53 | + descripciones: Mapped[list[dict[str, Any]] | None] = mapped_column(JSONB) | ||
| 54 | + | ||
| 55 | + | ||
| 56 | +class ClasRubros(Base): | ||
| 57 | + __tablename__ = "clas_rubros" | ||
| 58 | + | ||
| 59 | + nivel: Mapped[str | None] = mapped_column(Text) | ||
| 60 | + rubro: Mapped[str] = mapped_column(Text, primary_key=True) | ||
| 61 | + desc_rubro: Mapped[str | None] = mapped_column(Text) | ||
| 62 | + | ||
| 63 | + gestiones: Mapped[str | None] = mapped_column(Text) | ||
| 64 | + n_gestiones: Mapped[int | None] = mapped_column(Integer) | ||
| 65 | + n_variaciones: Mapped[int | None] = mapped_column(Integer) | ||
| 66 | + | ||
| 67 | + descripciones: Mapped[list[dict[str, Any]] | None] = mapped_column(JSONB) | ||
| 68 | + | ||
| 69 | + | ||
| 70 | +class ClasFinfun(Base): | ||
| 71 | + __tablename__ = "clas_finfun" | ||
| 72 | + | ||
| 73 | + nivel: Mapped[str | None] = mapped_column(Text) | ||
| 74 | + finfun: Mapped[str] = mapped_column(Text, primary_key=True) | ||
| 75 | + desc_finfun: Mapped[str | None] = mapped_column(Text) | ||
| 76 | + | ||
| 77 | + gestiones: Mapped[str | None] = mapped_column(Text) | ||
| 78 | + n_gestiones: Mapped[int | None] = mapped_column(Integer) | ||
| 79 | + n_variaciones: Mapped[int | None] = mapped_column(Integer) | ||
| 80 | + | ||
| 81 | + descripciones: Mapped[list[dict[str, Any]] | None] = mapped_column(JSONB) |
schemas/finfun.py
0 → 100644
| 1 | +from sqlalchemy.orm import Mapped, mapped_column | ||
| 2 | +from presupuestov1.schema import BaseModel | ||
| 3 | + | ||
| 4 | +from sqlalchemy import ( | ||
| 5 | + Integer, | ||
| 6 | + String, | ||
| 7 | + Text, | ||
| 8 | + Numeric, | ||
| 9 | + Index, | ||
| 10 | + MetaData, | ||
| 11 | +) | ||
| 12 | + | ||
| 13 | + | ||
| 14 | +class EntidadesPorFinfun(BaseModel): | ||
| 15 | + __tablename__ = "entidades_por_finfun" | ||
| 16 | + __table_args__ = ( | ||
| 17 | + Index("idx_entidades_por_finfun_finfun", "finfun"), | ||
| 18 | + Index("idx_entidades_por_finfun_finfun_nivel", "finfun", "nivel"), | ||
| 19 | + ) | ||
| 20 | + | ||
| 21 | + finfun: Mapped[str] = mapped_column(Text, primary_key=True) | ||
| 22 | + entidad: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 23 | + nivel: Mapped[str] = mapped_column(Text, primary_key=True) | ||
| 24 | + | ||
| 25 | + entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +class FinfunEstado(BaseModel): | ||
| 29 | + __tablename__ = "finfun_estado" | ||
| 30 | + __table_args__ = ( | ||
| 31 | + Index("idx_finfun_estado_finfun", "finfun"), | ||
| 32 | + Index("idx_finfun_estado_finfun_gestion", "finfun", "gestion"), | ||
| 33 | + ) | ||
| 34 | + | ||
| 35 | + gestion: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 36 | + finfun: Mapped[str] = mapped_column(Text, primary_key=True) | ||
| 37 | + | ||
| 38 | + total: Mapped[float | None] = mapped_column(Numeric) | ||
| 39 | + poblacion: Mapped[int | None] = mapped_column(Integer) | ||
| 40 | + n_entidades: Mapped[int | None] = mapped_column(Integer) | ||
| 41 | + per_capita: Mapped[float | None] = mapped_column(Numeric) | ||
| 42 | + total_gestion: Mapped[float | None] = mapped_column(Numeric) | ||
| 43 | + prop: Mapped[float | None] = mapped_column(Numeric) | ||
| 44 | + ranking: Mapped[int | None] = mapped_column(Integer) | ||
| 45 | + n_pares: Mapped[int | None] = mapped_column(Integer) | ||
| 46 | + | ||
| 47 | + top1_entidad: Mapped[int | None] = mapped_column(Integer) | ||
| 48 | + top1_entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 49 | + top1_monto: Mapped[float | None] = mapped_column(Numeric) | ||
| 50 | + top1_pct: Mapped[float | None] = mapped_column(Numeric) | ||
| 51 | + | ||
| 52 | + top2_entidad: Mapped[int | None] = mapped_column(Integer) | ||
| 53 | + top2_entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 54 | + top2_monto: Mapped[float | None] = mapped_column(Numeric) | ||
| 55 | + top2_pct: Mapped[float | None] = mapped_column(Numeric) | ||
| 56 | + | ||
| 57 | + top3_entidad: Mapped[int | None] = mapped_column(Integer) | ||
| 58 | + top3_entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 59 | + top3_monto: Mapped[float | None] = mapped_column(Numeric) | ||
| 60 | + top3_pct: Mapped[float | None] = mapped_column(Numeric) | ||
| 61 | + | ||
| 62 | + | ||
| 63 | +class FinfunEntidad(BaseModel): | ||
| 64 | + __tablename__ = "finfun_entidad" | ||
| 65 | + __table_args__ = ( | ||
| 66 | + Index("idx_finfun_entidad_finfun", "finfun"), | ||
| 67 | + Index("idx_finfun_entidad_finfun_entidad", "finfun", "entidad"), | ||
| 68 | + ) | ||
| 69 | + | ||
| 70 | + gestion: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 71 | + finfun: Mapped[str] = mapped_column(Text, primary_key=True) | ||
| 72 | + entidad: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 73 | + | ||
| 74 | + nivel: Mapped[str | None] = mapped_column(Text) | ||
| 75 | + entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 76 | + monto: Mapped[float | None] = mapped_column(Numeric) | ||
| 77 | + per_capita: Mapped[float | None] = mapped_column(Numeric) | ||
| 78 | + ranking: Mapped[int | None] = mapped_column(Integer) | ||
| 79 | + prop: Mapped[float | None] = mapped_column(Numeric) | ||
| 80 | + n_entidades: Mapped[int | None] = mapped_column(Integer) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
schemas/objeto.py
0 → 100644
| 1 | +from sqlalchemy.orm import Mapped, mapped_column | ||
| 2 | +from presupuestov1.schema import BaseModel | ||
| 3 | + | ||
| 4 | +from sqlalchemy import ( | ||
| 5 | + Integer, | ||
| 6 | + String, | ||
| 7 | + Text, | ||
| 8 | + Numeric, | ||
| 9 | + Index, | ||
| 10 | + MetaData, | ||
| 11 | +) | ||
| 12 | + | ||
| 13 | + | ||
| 14 | +class EntidadesPorObjeto(BaseModel): | ||
| 15 | + __tablename__ = "entidades_por_objeto" | ||
| 16 | + __table_args__ = ( | ||
| 17 | + Index("idx_entidades_por_objeto_objeto", "objeto"), | ||
| 18 | + Index("idx_entidades_por_objeto_objeto_nivel", "objeto", "nivel"), | ||
| 19 | + ) | ||
| 20 | + | ||
| 21 | + entidad: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 22 | + objeto: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 23 | + nivel: Mapped[str] = mapped_column(String(20), primary_key=True) | ||
| 24 | + | ||
| 25 | + entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +class ObjetoEstado(BaseModel): | ||
| 29 | + __tablename__ = "objeto_estado" | ||
| 30 | + __table_args__ = ( | ||
| 31 | + Index("idx_objeto_estado_objeto", "objeto"), | ||
| 32 | + Index("idx_objeto_estado_objeto_gestion", "objeto", "gestion"), | ||
| 33 | + ) | ||
| 34 | + | ||
| 35 | + gestion: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 36 | + objeto: Mapped[str] = mapped_column(Text, primary_key=True) | ||
| 37 | + | ||
| 38 | + total: Mapped[float | None] = mapped_column(Numeric) | ||
| 39 | + poblacion: Mapped[int | None] = mapped_column(Integer) | ||
| 40 | + n_entidades: Mapped[int | None] = mapped_column(Integer) | ||
| 41 | + per_capita: Mapped[float | None] = mapped_column(Numeric) | ||
| 42 | + total_gestion: Mapped[float | None] = mapped_column(Numeric) | ||
| 43 | + prop: Mapped[float | None] = mapped_column(Numeric) | ||
| 44 | + ranking: Mapped[int | None] = mapped_column(Integer) | ||
| 45 | + n_pares: Mapped[int | None] = mapped_column(Integer) | ||
| 46 | + | ||
| 47 | + top1_entidad: Mapped[int | None] = mapped_column(Integer) | ||
| 48 | + top1_entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 49 | + top1_monto: Mapped[float | None] = mapped_column(Numeric) | ||
| 50 | + top1_pct: Mapped[float | None] = mapped_column(Numeric) | ||
| 51 | + | ||
| 52 | + top2_entidad: Mapped[int | None] = mapped_column(Integer) | ||
| 53 | + top2_entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 54 | + top2_monto: Mapped[float | None] = mapped_column(Numeric) | ||
| 55 | + top2_pct: Mapped[float | None] = mapped_column(Numeric) | ||
| 56 | + | ||
| 57 | + top3_entidad: Mapped[int | None] = mapped_column(Integer) | ||
| 58 | + top3_entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 59 | + top3_monto: Mapped[float | None] = mapped_column(Numeric) | ||
| 60 | + top3_pct: Mapped[float | None] = mapped_column(Numeric) | ||
| 61 | + | ||
| 62 | + | ||
| 63 | +class ObjetoEntidad(BaseModel): | ||
| 64 | + __tablename__ = "objeto_entidad" | ||
| 65 | + __table_args__ = ( | ||
| 66 | + Index("idx_finfun_entidad_objeto", "objeto"), | ||
| 67 | + Index("idx_finfun_entidad_objeto_entidad", "objeto", "entidad"), | ||
| 68 | + ) | ||
| 69 | + | ||
| 70 | + gestion: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 71 | + objeto: Mapped[str] = mapped_column(Text, primary_key=True) | ||
| 72 | + entidad: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 73 | + | ||
| 74 | + nivel: Mapped[str | None] = mapped_column(Text) | ||
| 75 | + entidad_desc: Mapped[str | None] = mapped_column(Text) | ||
| 76 | + monto: Mapped[float | None] = mapped_column(Numeric) | ||
| 77 | + per_capita: Mapped[float | None] = mapped_column(Numeric) | ||
| 78 | + ranking: Mapped[int | None] = mapped_column(Integer) | ||
| 79 | + prop: Mapped[float | None] = mapped_column(Numeric) | ||
| 80 | + n_entidades: Mapped[int | None] = mapped_column(Integer) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
schemas/project.py
0 → 100644
| 1 | +from typing import List, Any, Dict | ||
| 2 | + | ||
| 3 | +from presupuestov1.schema import BaseModel | ||
| 4 | + | ||
| 5 | + | ||
| 6 | +class ProjectSearch(BaseModel): | ||
| 7 | + gestion: int | ||
| 8 | + entidad: int | ||
| 9 | + programa: int | ||
| 10 | + proyecto: str | ||
| 11 | + actividad: int | ||
| 12 | + desc_programa: str | ||
| 13 | + desc_actividad_proyecto: str | ||
| 14 | + devengado: float | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +class SearchHitHighlight(BaseModel): | ||
| 18 | + field: str | ||
| 19 | + matched_tokens: List[str] | ||
| 20 | + snippet: str | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +class SearchHits(BaseModel): | ||
| 24 | + document: ProjectSearch | ||
| 25 | + highlights: List[SearchHitHighlight] | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +class SearchFacet_(BaseModel): | ||
| 29 | + value: str | ||
| 30 | + count: int | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +class SearchFacet(BaseModel): | ||
| 34 | + counts: List[SearchFacet_] | ||
| 35 | + field_name: str | ||
| 36 | + | ||
| 37 | + | ||
| 38 | +class Search(BaseModel): | ||
| 39 | + facet_counts: List[SearchFacet] | ||
| 40 | + found: int | ||
| 41 | + out_of: int | ||
| 42 | + page: int | ||
| 43 | + search_time_ms: int | ||
| 44 | + hits: List[SearchHits] | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
schemas/treemap.py
0 → 100644
| 1 | +from sqlalchemy.orm import Mapped, mapped_column | ||
| 2 | +from presupuestov1.schema import BaseModel | ||
| 3 | + | ||
| 4 | +from sqlalchemy import ( | ||
| 5 | + Integer, | ||
| 6 | + String, | ||
| 7 | + Text, | ||
| 8 | + Numeric, | ||
| 9 | + Index, | ||
| 10 | + MetaData, | ||
| 11 | +) | ||
| 12 | + | ||
| 13 | + | ||
| 14 | +class TreemapObjeto(BaseModel): | ||
| 15 | + __tablename__ = "treemap_objeto" | ||
| 16 | + __table_args__ = ( | ||
| 17 | + Index("idx_treemap_objeto_gestion_entidad", "gestion", "entidad"), | ||
| 18 | + ) | ||
| 19 | + | ||
| 20 | + # PK compuesta inferida para uso ORM | ||
| 21 | + gestion: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 22 | + entidad: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 23 | + nivel: Mapped[str] = mapped_column(String(20), primary_key=True) | ||
| 24 | + objeto: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 25 | + | ||
| 26 | + desc_objeto: Mapped[str | None] = mapped_column(Text) | ||
| 27 | + parent: Mapped[int | None] = mapped_column(Integer) | ||
| 28 | + devengado: Mapped[float | None] = mapped_column(Numeric) | ||
| 29 | + | ||
| 30 | + | ||
| 31 | +class TreemapFinFun(BaseModel): | ||
| 32 | + __tablename__ = "treemap_finfun" | ||
| 33 | + __table_args__ = ( | ||
| 34 | + Index("idx_treemap_finfun_gestion_entidad", "gestion", "entidad"), | ||
| 35 | + ) | ||
| 36 | + | ||
| 37 | + # PK compuesta inferida para uso ORM | ||
| 38 | + gestion: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 39 | + entidad: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 40 | + nivel: Mapped[str] = mapped_column(String(20), primary_key=True) | ||
| 41 | + finfun: Mapped[int] = mapped_column(String(9), primary_key=True) | ||
| 42 | + | ||
| 43 | + desc_finfun: Mapped[str | None] = mapped_column(Text) | ||
| 44 | + parent: Mapped[int | None] = mapped_column(Integer) | ||
| 45 | + devengado: Mapped[float | None] = mapped_column(Numeric) | ||
| 46 | + | ||
| 47 | + | ||
| 48 | +class TreemapActeco(BaseModel): | ||
| 49 | + __tablename__ = "treemap_acteco" | ||
| 50 | + __table_args__ = ( | ||
| 51 | + Index("idx_treemap_acteco_gestion_entidad", "gestion", "entidad"), | ||
| 52 | + ) | ||
| 53 | + | ||
| 54 | + # PK compuesta inferida para uso ORM | ||
| 55 | + gestion: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 56 | + entidad: Mapped[int] = mapped_column(Integer, primary_key=True) | ||
| 57 | + nivel: Mapped[str] = mapped_column(String(20), primary_key=True) | ||
| 58 | + acteco: Mapped[int] = mapped_column(String(9), primary_key=True) | ||
| 59 | + | ||
| 60 | + desc_actividad: Mapped[str | None] = mapped_column(Text) | ||
| 61 | + parent: Mapped[int | None] = mapped_column(Integer) | ||
| 62 | + devengado: Mapped[float | None] = mapped_column(Numeric) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
search.py
0 → 100644
| 1 | +import typesense | ||
| 2 | + | ||
| 3 | +TYPESENSE_API = open('./docs/typesense').read().strip() | ||
| 4 | +client = typesense.Client({ | ||
| 5 | + 'api_key': TYPESENSE_API, | ||
| 6 | + 'nodes': [{ | ||
| 7 | + 'host': 'localhost', | ||
| 8 | + 'port': '8108', | ||
| 9 | + 'protocol': 'http' | ||
| 10 | + }], | ||
| 11 | + 'connection_timeout_seconds': 2 | ||
| 12 | +}) | ||
| 13 | + | ||
| 14 | +COLLECTION = 'presup_actpro_fts' | ||
| 15 | +schema = { | ||
| 16 | + 'name': COLLECTION, | ||
| 17 | + 'fields': [ | ||
| 18 | + {'name': 'index', 'type': 'int32'}, | ||
| 19 | + {'name': 'gestion', 'type': 'int32', 'facet': True}, | ||
| 20 | + {'name': 'entidad', 'type': 'int32',}, | ||
| 21 | + {'name': 'programa', 'type': 'int32',}, | ||
| 22 | + {'name': 'proyecto', 'type': 'string',}, | ||
| 23 | + {'name': 'actividad', 'type': 'int32',}, | ||
| 24 | + {'name': 'desc_actividad_proyecto', 'type': 'string'}, | ||
| 25 | + {'name': 'devengado', 'type': 'float'}, | ||
| 26 | + ], | ||
| 27 | + 'default_sorting_field': 'devengado', | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +search_parameters = { | ||
| 31 | + "q": "cuba", | ||
| 32 | + "query_by": "desc_actividad_proyecto,desc_programa", | ||
| 33 | + "facet_by": "gestion", | ||
| 34 | + "sort_by": "devengado:desc", | ||
| 35 | + "per_page": 20, | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + | ||
| 40 | +def do_search(query, page): | ||
| 41 | + search_parameters_ = search_parameters.copy() | ||
| 42 | + search_parameters_['q'] = query | ||
| 43 | + | ||
| 44 | + if (page is not None) and (page > 0): | ||
| 45 | + search_parameters_['page'] = page | ||
| 46 | + | ||
| 47 | + return client.collections[COLLECTION].documents.search( | ||
| 48 | + search_parameters_ | ||
| 49 | + ) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment