pr0nstar

IX

1 +# cache_patch.py
2 +import hashlib
3 +from datetime import datetime
4 +
5 +from starlette_caches.utils import cache as scache
6 +from aiocache import Cache
7 +
8 +
9 +REDIS_CONN = open('./docs/postgres').read().strip()
10 +REDIS_CONN = REDIS_CONN.split(':')
11 +# cache = Cache(
12 +# Cache.REDIS,
13 +# endpoint=REDIS_CONN[0], port=REDIS_CONN[1],
14 +# namespace="httpcache"
15 +# )
16 +cache = Cache()
17 +
18 +
19 +def patched_generate_cache_key(url, method, headers, varying_headers, cache):
20 + assert method in scache.CACHABLE_METHODS
21 +
22 + # vary_ctx = hashlib.md5(usedforsecurity=False)
23 + # for header in varying_headers:
24 + # value = headers.get(header)
25 + # if value is not None:
26 + # vary_ctx.update(value.encode())
27 + #
28 + # vary_hash = vary_ctx.hexdigest()
29 + url_hash = hashlib.md5(
30 + str(url).encode("ascii"), usedforsecurity=False
31 + ).hexdigest()
32 +
33 + now = datetime.now()
34 + dataset_version = now.strftime('%Y%m%d')
35 +
36 + return f"cache_presupuestov1.{dataset_version}.{method}.{url_hash}"
37 +
38 +
39 +scache.generate_cache_key = patched_generate_cache_key
1 +import re
1 import logging 2 import logging
2 3
3 from typing import Any, Union 4 from typing import Any, Union
...@@ -10,12 +11,16 @@ from starlette.requests import HTTPConnection, Request ...@@ -10,12 +11,16 @@ from starlette.requests import HTTPConnection, Request
10 from starlette_context import context, plugins 11 from starlette_context import context, plugins
11 from starlette_context.middleware import RawContextMiddleware 12 from starlette_context.middleware import RawContextMiddleware
12 13
13 -from aiocache import caches 14 +from starlette.middleware import Middleware
15 +from starlette_caches.middleware import CacheMiddleware
16 +from starlette_caches.rules import Rule
14 17
18 +from presupuestov1 import cache
15 from presupuestov1.routers import ( 19 from presupuestov1.routers import (
16 project, 20 project,
17 entity, 21 entity,
18 classifier, 22 classifier,
23 + classifier_income,
19 daily, 24 daily,
20 ) 25 )
21 26
...@@ -36,7 +41,15 @@ app = FastAPI( ...@@ -36,7 +41,15 @@ app = FastAPI(
36 plugins=( 41 plugins=(
37 plugins.RequestIdPlugin(), 42 plugins.RequestIdPlugin(),
38 ) 43 )
39 - ) 44 + ),
45 + Middleware(
46 + CacheMiddleware,
47 + cache=cache.cache,
48 + rules=[
49 + Rule(match=re.compile(r"^/api/proyecto/.*"), ttl=0),
50 + Rule(match=re.compile(r'^/api/.+'), ttl=86400, status=200),
51 + ],
52 + ),
40 ], 53 ],
41 root_path='/api' 54 root_path='/api'
42 ) 55 )
...@@ -47,23 +60,25 @@ app.include_router(entity.router_da) ...@@ -47,23 +60,25 @@ app.include_router(entity.router_da)
47 app.include_router(classifier.router_objeto) 60 app.include_router(classifier.router_objeto)
48 app.include_router(classifier.router_acteco) 61 app.include_router(classifier.router_acteco)
49 app.include_router(classifier.router_finfun) 62 app.include_router(classifier.router_finfun)
63 +app.include_router(classifier_income.router_rubro)
64 +app.include_router(classifier_income.router_organismo)
50 app.include_router(daily.router) 65 app.include_router(daily.router)
51 66
52 67
53 68
54 -@app.on_event('startup') 69 +# @app.on_event('startup')
55 -async def startup_event(): 70 +# async def startup_event():
56 - caches.set_config({ 71 +# caches.set_config({
57 - 'default': { 72 +# 'default': {
58 - 'cache': 'aiocache.SimpleMemoryCache', 73 +# 'cache': 'aiocache.SimpleMemoryCache',
59 - 'serializer': { 74 +# 'serializer': {
60 - 'class': 'aiocache.serializers.StringSerializer' # Cache raw text 75 +# 'class': 'aiocache.serializers.StringSerializer' # Cache raw text
61 - } 76 +# }
62 - } 77 +# }
63 - }) 78 +# })
64 - 79 +#
65 -@app.on_event('shutdown') 80 +# @app.on_event('shutdown')
66 -async def shutdown_event(): 81 +# async def shutdown_event():
67 - default_cache = caches.get('default') 82 +# default_cache = caches.get('default')
68 - if hasattr(default_cache, 'close'): 83 +# if hasattr(default_cache, 'close'):
69 - await default_cache.close() 84 +# await default_cache.close()
......
...@@ -5,5 +5,7 @@ from . import ( ...@@ -5,5 +5,7 @@ from . import (
5 objeto, 5 objeto,
6 treemap, 6 treemap,
7 entity, 7 entity,
8 + rubro,
9 + organismo,
8 daily, 10 daily,
9 ) 11 )
......
...@@ -73,3 +73,28 @@ class ActecoEntidad(Base): ...@@ -73,3 +73,28 @@ class ActecoEntidad(Base):
73 ranking: Mapped[int | None] = mapped_column(Integer) 73 ranking: Mapped[int | None] = mapped_column(Integer)
74 prop: Mapped[float | None] = mapped_column(Numeric) 74 prop: Mapped[float | None] = mapped_column(Numeric)
75 n_entidades: Mapped[int | None] = mapped_column(Integer) 75 n_entidades: Mapped[int | None] = mapped_column(Integer)
76 +
77 +
78 +class ActecoUbigeo(Base):
79 + __tablename__ = "acteco_ubigeo"
80 + __table_args__ = (
81 + Index("idx_acteco_ubigeo_gestion", "gestion"),
82 + Index("idx_acteco_ubigeo_acteco", "acteco"),
83 + Index("idx_acteco_ubigeo_acteco_entidad", "acteco", "ubigeo"),
84 + {"schema": "web"},
85 + )
86 +
87 + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
88 +
89 + gestion: Mapped[int] = mapped_column(Integer)
90 + acteco: Mapped[str] = mapped_column(String(9))
91 + ubigeo: Mapped[int] = mapped_column(String(9))
92 +
93 + nivel: Mapped[str | None] = mapped_column(Text)
94 + desc_ubigeo: Mapped[str | None] = mapped_column(Text)
95 + desc_departamento: Mapped[str | None] = mapped_column(Text)
96 + monto: Mapped[float | None] = mapped_column(Numeric(30, 15))
97 + per_capita: Mapped[float | None] = mapped_column(Numeric)
98 + ranking: Mapped[int | None] = mapped_column(Integer)
99 + prop: Mapped[float | None] = mapped_column(Numeric)
100 + n_entidades: Mapped[int | None] = mapped_column(Integer)
......
...@@ -87,3 +87,28 @@ class FinfunEntidad(Base): ...@@ -87,3 +87,28 @@ class FinfunEntidad(Base):
87 ranking: Mapped[int | None] = mapped_column(Integer) 87 ranking: Mapped[int | None] = mapped_column(Integer)
88 prop: Mapped[float | None] = mapped_column(Numeric) 88 prop: Mapped[float | None] = mapped_column(Numeric)
89 n_entidades: Mapped[int | None] = mapped_column(Integer) 89 n_entidades: Mapped[int | None] = mapped_column(Integer)
90 +
91 +
92 +class FinfunUbigeo(Base):
93 + __tablename__ = "finfun_ubigeo"
94 + __table_args__ = (
95 + Index("idx_finfun_ubigeo_gestion", "gestion"),
96 + Index("idx_finfun_ubigeo_finfun", "finfun"),
97 + Index("idx_finfun_ubigeo_finfun_entidad", "finfun", "ubigeo"),
98 + {"schema": "web"},
99 + )
100 +
101 + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
102 +
103 + gestion: Mapped[int] = mapped_column(Integer)
104 + finfun: Mapped[str] = mapped_column(String(11))
105 + ubigeo: Mapped[int] = mapped_column(String(9))
106 +
107 + nivel: Mapped[str | None] = mapped_column(Text)
108 + desc_ubigeo: Mapped[str | None] = mapped_column(Text)
109 + desc_departamento: Mapped[str | None] = mapped_column(Text)
110 + monto: Mapped[float | None] = mapped_column(Numeric(30, 15))
111 + per_capita: Mapped[float | None] = mapped_column(Numeric)
112 + ranking: Mapped[int | None] = mapped_column(Integer)
113 + prop: Mapped[float | None] = mapped_column(Numeric)
114 + n_entidades: Mapped[int | None] = mapped_column(Integer)
......
...@@ -88,3 +88,28 @@ class ObjetoEntidad(Base): ...@@ -88,3 +88,28 @@ class ObjetoEntidad(Base):
88 ranking: Mapped[int | None] = mapped_column(Integer) 88 ranking: Mapped[int | None] = mapped_column(Integer)
89 prop: Mapped[float | None] = mapped_column(Numeric) 89 prop: Mapped[float | None] = mapped_column(Numeric)
90 n_entidades: Mapped[int | None] = mapped_column(Integer) 90 n_entidades: Mapped[int | None] = mapped_column(Integer)
91 +
92 +
93 +class ObjetoUbigeo(Base):
94 + __tablename__ = "objeto_ubigeo"
95 + __table_args__ = (
96 + Index("idx_objeto_ubigeo_gestion", "gestion"),
97 + Index("idx_objeto_ubigeo_objeto", "objeto"),
98 + Index("idx_objeto_ubigeo_objeto_entidad", "objeto", "ubigeo"),
99 + {"schema": "web"},
100 + )
101 +
102 + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
103 +
104 + gestion: Mapped[int] = mapped_column(Integer)
105 + objeto: Mapped[str] = mapped_column(String(9))
106 + ubigeo: Mapped[int] = mapped_column(String(9))
107 +
108 + nivel: Mapped[str | None] = mapped_column(Text)
109 + desc_ubigeo: Mapped[str | None] = mapped_column(Text)
110 + desc_departamento: Mapped[str | None] = mapped_column(Text)
111 + monto: Mapped[float | None] = mapped_column(Numeric(30, 15))
112 + per_capita: Mapped[float | None] = mapped_column(Numeric)
113 + ranking: Mapped[int | None] = mapped_column(Integer)
114 + prop: Mapped[float | None] = mapped_column(Numeric)
115 + n_entidades: Mapped[int | None] = mapped_column(Integer)
......
1 +from sqlalchemy.orm import Mapped, mapped_column
2 +from presupuestov1.model import Base
3 +
4 +from sqlalchemy import (
5 + Integer,
6 + String,
7 + Text,
8 + Numeric,
9 + Index,
10 + MetaData,
11 +)
12 +
13 +
14 +class OrganismoEstado(Base):
15 + __tablename__ = "organismo_estado"
16 + __table_args__ = (
17 + Index("idx_organismo_estado_gestion", "gestion"),
18 + Index("idx_organismo_estado_organismo", "organismo"),
19 + Index("idx_organismo_estado_organismo_gestion", "organismo", "gestion"),
20 + {"schema": "web"},
21 + )
22 +
23 + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
24 +
25 + gestion: Mapped[int] = mapped_column(Integer)
26 + organismo: Mapped[str] = mapped_column(Text)
27 + nivel: Mapped[str | None] = mapped_column(Text)
28 +
29 + total: Mapped[float | None] = mapped_column(Numeric(30, 15))
30 + poblacion: Mapped[int | None] = mapped_column(Numeric)
31 + n_entidades: Mapped[int | None] = mapped_column(Integer)
32 + per_capita: Mapped[float | None] = mapped_column(Numeric)
33 + total_gestion: Mapped[float | None] = mapped_column(Numeric(30, 15))
34 + prop: Mapped[float | None] = mapped_column(Numeric)
35 + ranking: Mapped[int | None] = mapped_column(Integer)
36 + n_pares: Mapped[int | None] = mapped_column(Integer)
37 +
38 + top1_entidad: Mapped[int | None] = mapped_column(Numeric)
39 + top1_entidad_desc: Mapped[str | None] = mapped_column(Text)
40 + top1_monto: Mapped[float | None] = mapped_column(Numeric(30, 15))
41 + top1_pct: Mapped[float | None] = mapped_column(Numeric)
42 +
43 + top2_entidad: Mapped[int | None] = mapped_column(Numeric)
44 + top2_entidad_desc: Mapped[str | None] = mapped_column(Text)
45 + top2_monto: Mapped[float | None] = mapped_column(Numeric(30, 15))
46 + top2_pct: Mapped[float | None] = mapped_column(Numeric)
47 +
48 + top3_entidad: Mapped[int | None] = mapped_column(Numeric)
49 + top3_entidad_desc: Mapped[str | None] = mapped_column(Text)
50 + top3_monto: Mapped[float | None] = mapped_column(Numeric(30, 15))
51 + top3_pct: Mapped[float | None] = mapped_column(Numeric)
52 +
53 +
54 +class OrganismoEntidad(Base):
55 + __tablename__ = "organismo_entidad"
56 + __table_args__ = (
57 + Index("idx_organismo_entidad_gestion", "gestion"),
58 + Index("idx_organismo_entidad_objeto", "organismo"),
59 + Index("idx_organismo_entidad_rubro_entidad", "organismo", "entidad"),
60 + {"schema": "web"},
61 + )
62 +
63 + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
64 +
65 + gestion: Mapped[int] = mapped_column(Integer)
66 + organismo: Mapped[str] = mapped_column(Text)
67 + entidad: Mapped[int] = mapped_column(Integer)
68 +
69 + nivel: Mapped[str | None] = mapped_column(Text)
70 + entidad_desc: Mapped[str | None] = mapped_column(Text)
71 + monto: Mapped[float | None] = mapped_column(Numeric(30, 15))
72 + per_capita: Mapped[float | None] = mapped_column(Numeric)
73 + ranking: Mapped[int | None] = mapped_column(Integer)
74 + prop: Mapped[float | None] = mapped_column(Numeric)
75 + n_entidades: Mapped[int | None] = mapped_column(Integer)
1 +from sqlalchemy.orm import Mapped, mapped_column
2 +from presupuestov1.model import Base
3 +
4 +from sqlalchemy import (
5 + Integer,
6 + String,
7 + Text,
8 + Numeric,
9 + Index,
10 + MetaData,
11 +)
12 +
13 +
14 +class RubroEstado(Base):
15 + __tablename__ = "rubro_estado"
16 + __table_args__ = (
17 + Index("idx_rubro_estado_gestion", "gestion"),
18 + Index("idx_rubro_estado_rubro", "rubro"),
19 + Index("idx_rubro_estado_rubro_gestion", "rubro", "gestion"),
20 + {"schema": "web"},
21 + )
22 +
23 + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
24 +
25 + gestion: Mapped[int] = mapped_column(Integer)
26 + rubro: Mapped[str] = mapped_column(Text)
27 + nivel: Mapped[str | None] = mapped_column(Text)
28 +
29 + total: Mapped[float | None] = mapped_column(Numeric(30, 15))
30 + poblacion: Mapped[int | None] = mapped_column(Numeric)
31 + n_entidades: Mapped[int | None] = mapped_column(Integer)
32 + per_capita: Mapped[float | None] = mapped_column(Numeric)
33 + total_gestion: Mapped[float | None] = mapped_column(Numeric(30, 15))
34 + prop: Mapped[float | None] = mapped_column(Numeric)
35 + ranking: Mapped[int | None] = mapped_column(Integer)
36 + n_pares: Mapped[int | None] = mapped_column(Integer)
37 +
38 + top1_entidad: Mapped[int | None] = mapped_column(Numeric)
39 + top1_entidad_desc: Mapped[str | None] = mapped_column(Text)
40 + top1_monto: Mapped[float | None] = mapped_column(Numeric(30, 15))
41 + top1_pct: Mapped[float | None] = mapped_column(Numeric)
42 +
43 + top2_entidad: Mapped[int | None] = mapped_column(Numeric)
44 + top2_entidad_desc: Mapped[str | None] = mapped_column(Text)
45 + top2_monto: Mapped[float | None] = mapped_column(Numeric(30, 15))
46 + top2_pct: Mapped[float | None] = mapped_column(Numeric)
47 +
48 + top3_entidad: Mapped[int | None] = mapped_column(Numeric)
49 + top3_entidad_desc: Mapped[str | None] = mapped_column(Text)
50 + top3_monto: Mapped[float | None] = mapped_column(Numeric(30, 15))
51 + top3_pct: Mapped[float | None] = mapped_column(Numeric)
52 +
53 +
54 +class RubroEntidad(Base):
55 + __tablename__ = "rubro_entidad"
56 + __table_args__ = (
57 + Index("idx_rubro_entidad_gestion", "gestion"),
58 + Index("idx_rubro_entidad_objeto", "rubro"),
59 + Index("idx_rubro_entidad_rubro_entidad", "rubro", "entidad"),
60 + {"schema": "web"},
61 + )
62 +
63 + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
64 +
65 + gestion: Mapped[int] = mapped_column(Integer)
66 + rubro: Mapped[str] = mapped_column(Text)
67 + entidad: Mapped[int] = mapped_column(Integer)
68 +
69 + nivel: Mapped[str | None] = mapped_column(Text)
70 + entidad_desc: Mapped[str | None] = mapped_column(Text)
71 + monto: Mapped[float | None] = mapped_column(Numeric(30, 15))
72 + per_capita: Mapped[float | None] = mapped_column(Numeric)
73 + ranking: Mapped[int | None] = mapped_column(Integer)
74 + prop: Mapped[float | None] = mapped_column(Numeric)
75 + n_entidades: Mapped[int | None] = mapped_column(Integer)
...@@ -84,6 +84,30 @@ class TreemapActeco(Base): ...@@ -84,6 +84,30 @@ class TreemapActeco(Base):
84 desc_acteco: Mapped[str | None] = mapped_column(Text) 84 desc_acteco: Mapped[str | None] = mapped_column(Text)
85 85
86 86
87 +class TreemapRubro(Base):
88 + __tablename__ = "treemap_rubro"
89 + __table_args__ = (
90 + Index("idx_treemap_rubro_gestion_entidad", "gestion", "entidad"),
91 + Index("idx_treemap_rubro_nivel", "nivel"),
92 + {"schema": "web"},
93 + )
94 +
95 + # PK compuesta inferida para uso ORM
96 + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
97 +
98 + gestion: Mapped[int] = mapped_column(Integer)
99 + entidad_area: Mapped[str | None] = mapped_column(String(9))
100 + entidad: Mapped[int] = mapped_column(Integer)
101 + rubro: Mapped[str] = mapped_column(String(9))
102 + nivel: Mapped[str | None] = mapped_column(String(20))
103 +
104 + parent: Mapped[str | None] = mapped_column(String(9))
105 + devengado: Mapped[float | None] = mapped_column(Numeric(30, 15))
106 +
107 + desc_entidad: Mapped[str | None] = mapped_column(Text)
108 + desc_rubro: Mapped[str | None] = mapped_column(Text)
109 +
110 +
87 ############################################################################### 111 ###############################################################################
88 # fns 112 # fns
89 ############################################################################### 113 ###############################################################################
......
...@@ -8,8 +8,6 @@ from sqlalchemy import and_, or_, select ...@@ -8,8 +8,6 @@ from sqlalchemy import and_, or_, select
8 8
9 from presupuestov1 import model, schema, constant, schemas, models, search 9 from presupuestov1 import model, schema, constant, schemas, models, search
10 10
11 -from aiocache import cached
12 -
13 11
14 router_objeto = APIRouter( 12 router_objeto = APIRouter(
15 prefix='/objeto', 13 prefix='/objeto',
...@@ -83,6 +81,21 @@ def fetch_objeto_entidad( ...@@ -83,6 +81,21 @@ def fetch_objeto_entidad(
83 ).mappings().all() 81 ).mappings().all()
84 82
85 83
84 +@router_objeto.get('/{object_id}/ubigeos', response_model=List[schemas.objeto.ObjetoUbigeo])
85 +def fetch_objeto_ubigeo(
86 + object_id: str,
87 + db: Session = Depends(model.get_db),
88 + query: schema.QueryParams = Depends(),
89 +):
90 + gestion = query.gestion or 0
91 + ClasObjetos = models.objeto.ObjetoUbigeo
92 +
93 + return db.query(ClasObjetos).filter(
94 + ClasObjetos.objeto == object_id,
95 + ClasObjetos.gestion == gestion
96 + ).all()
97 +
98 +
86 @router_objeto.get('/{object_id}/entidades/map', response_model=List[schemas.treemap.TreemapObjetoSingle]) 99 @router_objeto.get('/{object_id}/entidades/map', response_model=List[schemas.treemap.TreemapObjetoSingle])
87 def fetch_objeto_treemap( 100 def fetch_objeto_treemap(
88 object_id: str, 101 object_id: str,
...@@ -111,6 +124,21 @@ def fetch_objeto_entidad_single( ...@@ -111,6 +124,21 @@ def fetch_objeto_entidad_single(
111 ).all() 124 ).all()
112 125
113 126
127 +@router_objeto.get('/{object_id}/ubigeos/{ubigeo_id}', response_model=List[schemas.objeto.ObjetoUbigeo])
128 +def fetch_objeto_ubigeo_single(
129 + object_id: str,
130 + ubigeo_id: str,
131 + db: Session = Depends(model.get_db),
132 + query: schema.QueryParams = Depends(),
133 +):
134 + ClasObjetos = models.objeto.ObjetoUbigeo
135 +
136 + return db.query(ClasObjetos).filter(
137 + ClasObjetos.objeto == object_id,
138 + ClasObjetos.ubigeo == ubigeo_id
139 + ).all()
140 +
141 +
114 @router_acteco.get('/{acteco_id}', response_model=schemas.acteco.ClasActecoEstados) 142 @router_acteco.get('/{acteco_id}', response_model=schemas.acteco.ClasActecoEstados)
115 def fetch_acteco_estado( 143 def fetch_acteco_estado(
116 acteco_id: str, 144 acteco_id: str,
...@@ -147,6 +175,21 @@ def fetch_acteco_entidad( ...@@ -147,6 +175,21 @@ def fetch_acteco_entidad(
147 ).mappings().all() 175 ).mappings().all()
148 176
149 177
178 +@router_acteco.get('/{acteco_id}/ubigeos', response_model=List[schemas.acteco.ActecoUbigeo])
179 +def fetch_acteco_ubigeo(
180 + acteco_id: str,
181 + db: Session = Depends(model.get_db),
182 + query: schema.QueryParams = Depends(),
183 +):
184 + gestion = query.gestion or 0
185 + ClasObjetos = models.objeto.ActecoUbigeo
186 +
187 + return db.query(ClasObjetos).filter(
188 + ClasObjetos.acteco == acteco_id,
189 + ClasObjetos.gestion == gestion
190 + ).all()
191 +
192 +
150 @router_acteco.get('/{acteco_id}/entidades/map', response_model=List[schemas.treemap.TreemapActecoSingle]) 193 @router_acteco.get('/{acteco_id}/entidades/map', response_model=List[schemas.treemap.TreemapActecoSingle])
151 def fetch_acteco_treemap( 194 def fetch_acteco_treemap(
152 acteco_id: str, 195 acteco_id: str,
...@@ -176,6 +219,21 @@ def fetch_acteco_entidad_single( ...@@ -176,6 +219,21 @@ def fetch_acteco_entidad_single(
176 ).all() 219 ).all()
177 220
178 221
222 +@router_acteco.get('/{acteco_id}/ubigeos/{ubigeo_id}', response_model=List[schemas.acteco.ActecoUbigeo])
223 +def fetch_acteco_ubigeo_single(
224 + acteco_id: str,
225 + ubigeo_id: str,
226 + db: Session = Depends(model.get_db),
227 + query: schema.QueryParams = Depends(),
228 +):
229 + ClasObjetos = models.acteco.ActecoUbigeo
230 +
231 + return db.query(ClasObjetos).filter(
232 + ClasObjetos.actecp == acteco_id,
233 + ClasObjetos.ubigeo == ubigeo_id
234 + ).all()
235 +
236 +
179 @router_finfun.get('/{finfun_id}', response_model=schemas.finfun.ClasFinfunEstados) 237 @router_finfun.get('/{finfun_id}', response_model=schemas.finfun.ClasFinfunEstados)
180 def fetch_finfun_estado( 238 def fetch_finfun_estado(
181 finfun_id: str, 239 finfun_id: str,
...@@ -212,6 +270,21 @@ def fetch_finfun_entidad( ...@@ -212,6 +270,21 @@ def fetch_finfun_entidad(
212 ).mappings().all() 270 ).mappings().all()
213 271
214 272
273 +@router_finfun.get('/{finfun_id}/ubigeos', response_model=List[schemas.finfun.FinfunUbigeo])
274 +def fetch_finfun_ubigeo(
275 + finfun_id: str,
276 + db: Session = Depends(model.get_db),
277 + query: schema.QueryParams = Depends(),
278 +):
279 + gestion = query.gestion or 0
280 + ClasObjetos = models.finfun.FinfunUbigeo
281 +
282 + return db.query(ClasObjetos).filter(
283 + ClasObjetos.finfun == finfun_id,
284 + ClasObjetos.gestion == gestion
285 + ).all()
286 +
287 +
215 @router_finfun.get('/{finfun_id}/entidades/map', response_model=List[schemas.treemap.TreemapFinFunSingle]) 288 @router_finfun.get('/{finfun_id}/entidades/map', response_model=List[schemas.treemap.TreemapFinFunSingle])
216 def fetch_finfun_treemap( 289 def fetch_finfun_treemap(
217 finfun_id: str, 290 finfun_id: str,
...@@ -241,6 +314,21 @@ def fetch_finfun_entidad_single( ...@@ -241,6 +314,21 @@ def fetch_finfun_entidad_single(
241 ).all() 314 ).all()
242 315
243 316
317 +@router_finfun.get('/{finfun_id}/ubigeos/{ubigeo_id}', response_model=List[schemas.finfun.FinfunUbigeo])
318 +def fetch_finfun_ubigeo_single(
319 + finfun_id: str,
320 + ubigeo_id: str,
321 + db: Session = Depends(model.get_db),
322 + query: schema.QueryParams = Depends(),
323 +):
324 + ClasObjetos = models.finfun.FinfunUbigeo
325 +
326 + return db.query(ClasObjetos).filter(
327 + ClasObjetos.finfun == finfun_id,
328 + ClasObjetos.ubigeo == ubigeo_id
329 + ).all()
330 +
331 +
244 ############################################################################### 332 ###############################################################################
245 # priv 333 # priv
246 ############################################################################### 334 ###############################################################################
......
1 +from typing import List
2 +
3 +from fastapi import APIRouter, Depends
4 +from sqlalchemy.orm import Session
5 +from sqlalchemy import select
6 +
7 +from presupuestov1 import model, schema, schemas, models
8 +
9 +
10 +router_rubro = APIRouter(
11 + prefix='/rubro',
12 + tags=['rubro'],
13 +)
14 +
15 +router_organismo = APIRouter(
16 + prefix='/organismo',
17 + tags=['organismo'],
18 +)
19 +
20 +
21 +###############################################################################
22 +# GET
23 +###############################################################################
24 +
25 +@router_rubro.get('/clasificador', response_model=List[schemas.classifier.ClasRubros])
26 +def fetch_rubro_classifier(db: Session = Depends(model.get_db)):
27 + return _fetch_classifier('rubro', db)
28 +
29 +
30 +@router_organismo.get('/clasificador', response_model=List[schemas.classifier.ClasOrganismos])
31 +def fetch_organismo_classifier(db: Session = Depends(model.get_db)):
32 + return _fetch_classifier('organismo', db)
33 +
34 +
35 +@router_rubro.get('/{rubro_id}', response_model=schemas.rubro.ClasRubrosEstados)
36 +def fetch_rubro_estado(
37 + rubro_id: str,
38 + db: Session = Depends(model.get_db),
39 +):
40 + ClasEstado = models.rubro.RubroEstado
41 + estados = db.query(ClasEstado).filter(
42 + ClasEstado.rubro == rubro_id,
43 + ).all()
44 +
45 + ClasRubros = models.classifier.ClasRubros
46 + rubro = db.query(ClasRubros).filter(
47 + ClasRubros.rubro == rubro_id
48 + ).one()
49 +
50 + setattr(rubro, 'estados', estados)
51 + return rubro
52 +
53 +
54 +@router_rubro.get('/{rubro_id}/entidades', response_model=List[schemas.rubro.RubroEntidad])
55 +def fetch_rubro_entidad(
56 + rubro_id: str,
57 + db: Session = Depends(model.get_db),
58 + query: schema.QueryParams = Depends(),
59 +):
60 + gestion = query.gestion or 0
61 + ClasRubros = models.rubro.RubroEntidad
62 +
63 + return db.execute(
64 + select(*model.model_columns(ClasRubros)).where(
65 + ClasRubros.rubro == rubro_id,
66 + ClasRubros.gestion == gestion
67 + )
68 + ).mappings().all()
69 +
70 +
71 +@router_rubro.get('/{rubro_id}/entidades/map', response_model=List[schemas.treemap.TreemapRubroSingle])
72 +def fetch_rubro_treemap(
73 + rubro_id: str,
74 + db: Session = Depends(model.get_db),
75 + query: schema.QueryParams = Depends(),
76 +):
77 + Treemap = models.treemap.TreemapRubro
78 + return models.treemap.get_clas_entities(
79 + [
80 + Treemap.rubro == rubro_id
81 + ], db, query, Treemap, 'entidad'
82 + )
83 +
84 +
85 +
86 +@router_rubro.get('/{rubro_id}/entidades/{entidad_id}', response_model=List[schemas.rubro.RubroEntidad])
87 +def fetch_rubro_entidad_single(
88 + rubro_id: str,
89 + entidad_id: int,
90 + db: Session = Depends(model.get_db),
91 + query: schema.QueryParams = Depends(),
92 +):
93 + ClasRubros = models.rubro.RubroEntidad
94 +
95 + return db.query(ClasRubros).filter(
96 + ClasRubros.rubro == rubro_id,
97 + ClasRubros.entidad == entidad_id
98 + ).all()
99 +
100 +
101 +@router_organismo.get('/{organismo_id}', response_model=schemas.organismo.ClasOrganismosEstados)
102 +def fetch_organismo_estado(
103 + organismo_id: str,
104 + db: Session = Depends(model.get_db),
105 +):
106 + ClasEstado = models.organismo.OrganismoEstado
107 + estados = db.query(ClasEstado).filter(
108 + ClasEstado.organismo == organismo_id
109 + ).all()
110 +
111 + ClasOrganismos = models.classifier.ClasOrganismos
112 + organismo = db.query(ClasOrganismos).filter(
113 + ClasOrganismos.organismo == organismo_id
114 + ).one()
115 +
116 + setattr(organismo, 'estados', estados)
117 + return organismo
118 +
119 +
120 +@router_organismo.get('/{organismo_id}/entidades', response_model=List[schemas.organismo.OrganismoEntidad])
121 +def fetch_organismo_entidad(
122 + organismo_id: str,
123 + db: Session = Depends(model.get_db),
124 + query: schema.QueryParams = Depends(),
125 +):
126 + gestion = query.gestion or 0
127 + ClasOrganismos = models.organismo.OrganismoEntidad
128 +
129 + return db.execute(
130 + select(*model.model_columns(ClasOrganismos)).where(
131 + ClasOrganismos.organismo == organismo_id,
132 + ClasOrganismos.gestion == gestion
133 + )
134 + ).mappings().all()
135 +
136 +
137 +@router_organismo.get('/{organismo_id}/entidades/{entidad_id}', response_model=List[schemas.organismo.OrganismoEntidad])
138 +def fetch_organismo_entidad_single(
139 + organismo_id: str,
140 + entidad_id: int,
141 + db: Session = Depends(model.get_db),
142 + query: schema.QueryParams = Depends(),
143 +):
144 + ClasOrganismos = models.organismo.OrganismoEntidad
145 +
146 + return db.query(ClasOrganismos).filter(
147 + ClasOrganismos.organismo == organismo_id,
148 + ClasOrganismos.entidad == entidad_id
149 + ).all()
150 +
151 +
152 +###############################################################################
153 +# priv
154 +###############################################################################
155 +
156 +def _fetch_classifier(clas, db):
157 + ClasObject = {
158 + 'rubro': models.classifier.ClasRubros,
159 + 'organismo': models.classifier.ClasOrganismos,
160 + }[clas]
161 + return db.query(ClasObject).all()
...@@ -134,6 +134,24 @@ def fetch_entity_actecos( ...@@ -134,6 +134,24 @@ def fetch_entity_actecos(
134 return get_distribuciones(db, 'municipio_ubigeo', ubigeo_id, 'acteco', query) 134 return get_distribuciones(db, 'municipio_ubigeo', ubigeo_id, 'acteco', query)
135 135
136 136
137 +@router_entidad.get('/{entity_id:str}/rubros', response_model=List[schemas.entity.EntidadDistribucion])
138 +def fetch_entity_rubros(
139 + entity_id: str,
140 + db: Session = Depends(model.get_db),
141 + query: schema.QueryParams = Depends(),
142 +):
143 + return get_distribuciones(db, 'entidad', entity_id, 'rubro', query)
144 +
145 +
146 +@router_entidad.get('/{entity_id:str}/organismos', response_model=List[schemas.entity.EntidadDistribucion])
147 +def fetch_entity_organismos(
148 + entity_id: str,
149 + db: Session = Depends(model.get_db),
150 + query: schema.QueryParams = Depends(),
151 +):
152 + return get_distribuciones(db, 'entidad', entity_id, 'organismo', query)
153 +
154 +
137 ############################################################################### 155 ###############################################################################
138 # private 156 # private
139 ############################################################################### 157 ###############################################################################
......
...@@ -3,6 +3,8 @@ from . import ( ...@@ -3,6 +3,8 @@ from . import (
3 acteco, 3 acteco,
4 finfun, 4 finfun,
5 objeto, 5 objeto,
6 + organismo,
7 + rubro,
6 treemap, 8 treemap,
7 project, 9 project,
8 entity, 10 entity,
......
...@@ -41,5 +41,19 @@ class ActecoEntidad(OrmBaseModel): ...@@ -41,5 +41,19 @@ class ActecoEntidad(OrmBaseModel):
41 n_entidades: int | None 41 n_entidades: int | None
42 42
43 43
44 +class ActecoUbigeo(OrmBaseModel):
45 + gestion: int
46 + acteco: str
47 + ubigeo: str
48 + nivel: str | None
49 + desc_ubigeo: str | None
50 + desc_departamento: str | None
51 + monto: float | None
52 + per_capita: float | None
53 + ranking: int | None
54 + prop: float | None
55 + n_entidades: int | None
56 +
57 +
44 class ClasActecoEstados(schemas.classifier.ClasActeco): 58 class ClasActecoEstados(schemas.classifier.ClasActeco):
45 estados: List[ActecoEstado] 59 estados: List[ActecoEstado]
......
...@@ -48,5 +48,19 @@ class FinfunEntidad(OrmBaseModel): ...@@ -48,5 +48,19 @@ class FinfunEntidad(OrmBaseModel):
48 n_entidades: int | None 48 n_entidades: int | None
49 49
50 50
51 +class FinfunUbigeo(OrmBaseModel):
52 + gestion: int
53 + finfun: str
54 + ubigeo: str
55 + nivel: str | None
56 + desc_ubigeo: str | None
57 + desc_departamento: str | None
58 + monto: float | None
59 + per_capita: float | None
60 + ranking: int | None
61 + prop: float | None
62 + n_entidades: int | None
63 +
64 +
51 class ClasFinfunEstados(schemas.classifier.ClasFinfun): 65 class ClasFinfunEstados(schemas.classifier.ClasFinfun):
52 estados: List[FinfunEstado] 66 estados: List[FinfunEstado]
......
...@@ -48,5 +48,19 @@ class ObjetoEntidad(OrmBaseModel): ...@@ -48,5 +48,19 @@ class ObjetoEntidad(OrmBaseModel):
48 n_entidades: int | None 48 n_entidades: int | None
49 49
50 50
51 +class ObjetoUbigeo(OrmBaseModel):
52 + gestion: int
53 + objeto: str
54 + ubigeo: str
55 + nivel: str | None
56 + desc_ubigeo: str | None
57 + desc_departamento: str | None
58 + monto: float | None
59 + per_capita: float | None
60 + ranking: int | None
61 + prop: float | None
62 + n_entidades: int | None
63 +
64 +
51 class ClasObjetosEstados(schemas.classifier.ClasObjetos): 65 class ClasObjetosEstados(schemas.classifier.ClasObjetos):
52 estados: List[ObjetoEstado] 66 estados: List[ObjetoEstado]
......
1 +from typing import List
2 +
3 +from presupuestov1.schema import OrmBaseModel
4 +from presupuestov1 import schemas
5 +
6 +
7 +class OrganismoEstado(OrmBaseModel):
8 + gestion: int
9 + organismo: str
10 + nivel: str | None
11 + total: float | None
12 + poblacion: float | None
13 + n_entidades: int | None
14 + per_capita: float | None
15 + total_gestion: float | None
16 + prop: float | None
17 + ranking: int | None
18 + n_pares: int | None
19 + top1_entidad: int | None
20 + top1_entidad_desc: str | None
21 + top1_monto: float | None
22 + top1_pct: float | None
23 + top2_entidad: int | None | float
24 + top2_entidad_desc: str | None
25 + top2_monto: float | None
26 + top2_pct: float | None
27 + top3_entidad: int | None | float
28 + top3_entidad_desc: str | None
29 + top3_monto: float | None
30 + top3_pct: float | None
31 +
32 +
33 +class OrganismoEntidad(OrmBaseModel):
34 + gestion: int
35 + organismo: str
36 + entidad: int
37 + nivel: str | None
38 + entidad_desc: str | None
39 + monto: float | None
40 + per_capita: float | None
41 + ranking: int | None
42 + prop: float | None
43 + n_entidades: int | None
44 +
45 +
46 +class ClasOrganismosEstados(schemas.classifier.ClasOrganismos):
47 + estados: List[OrganismoEstado]
1 +from typing import List
2 +
3 +from presupuestov1.schema import OrmBaseModel
4 +from presupuestov1 import schemas
5 +
6 +
7 +class RubroEstado(OrmBaseModel):
8 + gestion: int
9 + rubro: str
10 + nivel: str | None
11 + total: float | None
12 + poblacion: float | None
13 + n_entidades: int | None
14 + per_capita: float | None
15 + total_gestion: float | None
16 + prop: float | None
17 + ranking: int | None
18 + n_pares: int | None
19 + top1_entidad: int | None
20 + top1_entidad_desc: str | None
21 + top1_monto: float | None
22 + top1_pct: float | None
23 + top2_entidad: int | None | float
24 + top2_entidad_desc: str | None
25 + top2_monto: float | None
26 + top2_pct: float | None
27 + top3_entidad: int | None | float
28 + top3_entidad_desc: str | None
29 + top3_monto: float | None
30 + top3_pct: float | None
31 +
32 +
33 +class RubroEntidad(OrmBaseModel):
34 + gestion: int
35 + rubro: str
36 + entidad: int
37 + nivel: str | None
38 + entidad_desc: str | None
39 + monto: float | None
40 + per_capita: float | None
41 + ranking: int | None
42 + prop: float | None
43 + n_entidades: int | None
44 +
45 +
46 +class ClasRubrosEstados(schemas.classifier.ClasRubros):
47 + estados: List[RubroEstado]
...@@ -53,3 +53,16 @@ class TreemapActecoSingle(Treemap): ...@@ -53,3 +53,16 @@ class TreemapActecoSingle(Treemap):
53 acteco: str 53 acteco: str
54 parent: str | None 54 parent: str | None
55 desc_entidad: str | None 55 desc_entidad: str | None
56 +
57 +
58 +class TreemapRubro(Treemap):
59 + rubro: str
60 + parent: str | None
61 + desc_rubro: str | None
62 + desc_entidad: str | None
63 +
64 +
65 +class TreemapRubroSingle(Treemap):
66 + rubro: str
67 + parent: str | None
68 + desc_entidad: str | None
......