gnit-api / README.md
Laevateinn707's picture
FK estudios->contactos (RESTRICT), correlativo RC en ingresos, codigos contables en saldos, endpoint /archivos (Supabase), pais_id en JWT y login; migraciones idempotentes en startup
a863251
|
Raw
History Blame Contribute Delete
40 kB
metadata
title: GNIT API
emoji: 🐳
colorFrom: purple
colorTo: gray
sdk: docker
app_port: 7860

GNIT API

API REST para la plataforma GNIT — gestión de miembros, contactos, estudios bíblicos, reportes, finanzas y más.

  • Stack: FastAPI + SQLAlchemy asyncio + PostgreSQL 16 (Neon)
  • Documentacion interactiva: /docs (Swagger UI) | /redoc (ReDoc)
  • Health check: /health

Base de Datos

Geografia

continentes

Campo Tipo Nulleable Default
id Integer PK NO
nombre String(100) NO

paises

Campo Tipo Nulleable Default
id Integer PK NO
iso String(2) SI
nombre String(100) NO
continente_id Integer FK → continentes SI SET NULL

ciudades

Campo Tipo Nulleable Default
id Integer PK NO
nombre String(100) NO
nombre_ascii String(100) SI
lat Numeric(10,7) SI
lng Numeric(10,7) SI
pais_iso2 String(2) FK → paises SI SET NULL
admin_name String(100) SI
capital String(20) SI
population BigInteger SI
worldcity_id BigInteger SI

Usuarios y Roles

usuarios

Campo Tipo Nulleable Default
id String(30) PK NO
nombre Text NO
email Text NO UNIQUE
password_hash Text NO
rol Integer FK → roles NO
fecha_registro DateTime NO utcnow
activo Boolean NO false
region String(20) SI
pais_id Integer FK → paises SI SET NULL
ciudad_id Integer FK → ciudades SI SET NULL
miembro_id String(30) FK → miembros SI SET NULL

roles

Campo Tipo Nulleable Default
id Integer PK NO
nombre String(30) NO ''
descripcion String(100) SI

rol_permisos

Campo Tipo Nulleable Default
rol_id Integer FK → roles NO PK
permiso_id Integer NO PK
activo Boolean SI true

usuario_permisos

Campo Tipo Nulleable Default
id Integer PK NO
usuario_id String(30) FK → usuarios NO CASCADE
permiso_id Integer NO
tiene_acceso Boolean SI true

Personas

miembros

Campo Tipo Nulleable Default
id String(30) PK NO
nombre Text NO
identidad String(30) SI
pais Text SI
ciudad Text SI
edad Integer SI
evangelizado_por Text SI
estado_civil Text SI
profesion Text SI
comentarios Text SI
tipo_miembro String(20) NO
pais_id Integer FK → paises SI SET NULL
ciudad_id Integer FK → ciudades SI SET NULL
cargo_funcion Text SI
ministerio_of Text SI
avance_audio Text SI

miembros_info_adicional

Campo Tipo Nulleable Default
id String(30) PK FK → miembros NO CASCADE
nombre_padre Text SI
telefono_padre String(30) SI
nombre_madre Text SI
telefono_madre String(30) SI
tipo_sangre String(5) SI
correo_electronico String(255) SI
fecha_creacion DateTime NO utcnow
fecha_actualizacion DateTime NO utcnow

contactos

Campo Tipo Nulleable Default
id Integer PK NO
miembro_responsable Text NO
nombre Text NO
telefono Text SI
pais Text SI
notas Text SI
profesion Text SI
fecha_creacion DateTime SI utcnow
pais_id Integer FK → paises SI SET NULL
miembro_responsable_id String(30) FK → miembros SI SET NULL
ciudad_id Integer FK → ciudades SI SET NULL

Misiones y Estudios

ciudades_mision

Campo Tipo Nulleable Default
id Integer PK NO
ciudad_id Integer FK → ciudades NO SET NULL
region String(150) SI
estado_presencia String(30) NO 'En proceso'
fecha_inicio_trabajo Date SI
pastor_encargado_id String(30) SI
pastor_encargado_nombre Text SI
cantidad_miembros_activos Integer SI 0
notas Text SI
fecha_creacion DateTime NO utcnow
fecha_actualizacion DateTime NO utcnow

reportes

Campo Tipo Nulleable Default
id Integer PK NO
miembro_que_reporta Text NO
fecha Date NO
tiempo_evangelizacion Interval SI
contactos_obtenidos Integer SI 0
contactos_estudian Integer SI 0
numero_estudios_dados Integer SI 0
total_estudiantes Integer SI 0
pais Text SI
fecha_creacion DateTime SI utcnow
pais_id Integer FK → paises SI SET NULL
miembro_id String(30) FK → miembros SI SET NULL
ciudad_id Integer FK → ciudades SI SET NULL

estudios_diarios

Campo Tipo Nulleable Default
id Integer PK NO
miembro_id String(30) FK → miembros NO CASCADE
pais_id Integer FK → paises SI SET NULL
contacto_id Integer FK → contactos SI RESTRICT
mes Integer NO
anio Integer NO
dia Integer NO
capitulo String(255) SI
horas Numeric(5,2) SI
tipo String(50) SI
donde String(255) SI
dijeron_si Integer SI 0
nuevos_contactos Integer SI 0
fecha_creacion DateTime NO utcnow

contacto_id usa ON DELETE RESTRICT: no se puede eliminar un contacto que tenga estudios registrados (el DELETE /contactos/{id} devuelve 409).


Finanzas

cotizaciones

Campo Tipo Nulleable Default
id Integer PK NO
fecha Date NO
solicitante Text NO
concepto Text NO
monto Numeric(15,2) NO
moneda String(10) NO 'USD'
estado String(20) NO 'pendiente'
agregado_a_gastos Boolean NO false
mes_agregado Integer SI
anio_agregado Integer SI
notas Text SI
fecha_creacion DateTime NO utcnow
fecha_actualizacion DateTime NO utcnow
miembro_id String(30) FK → miembros SI SET NULL

presupuestos

Campo Tipo Nulleable Default
id Integer PK NO
pais String(100) NO
mes Integer SI
anio Integer NO
tipo_gasto String(100) NO
concepto Text SI
monto Numeric(15,2) NO
moneda String(10) NO
tasa_cambio Numeric(15,6) SI
notas Text SI
fecha_registro DateTime SI utcnow
pais_id Integer FK → paises SI SET NULL

ejecuciones

Campo Tipo Nulleable Default
id Integer PK NO
pais String(100) NO
mes Integer NO
anio Integer NO
monto_recibido_usd Numeric(15,2) NO
presupuesto_id Integer FK → presupuestos SI SET NULL
notas Text SI
fecha_creacion DateTime NO utcnow
fecha_actualizacion DateTime NO utcnow
pais_id Integer FK → paises SI SET NULL

gastos_reales

Campo Tipo Nulleable Default
id Integer PK NO
ejecucion_id Integer FK → ejecuciones NO CASCADE
concepto Text NO
monto Numeric(15,2) NO
tipo_gasto String(100) NO
fecha_creacion DateTime NO utcnow

ingresos

Campo Tipo Nulleable Default
id Integer PK NO
numero String(20) SI
pais_id Integer FK → paises SI SET NULL
mes Integer NO
anio Integer NO
tipo String(100) NO
origen Text SI
donde_ingresa String(10) NO
valor Numeric(15,2) NO
observaciones Text SI
fecha Date NO
fecha_creacion DateTime NO utcnow

numero es un correlativo automático por país + año + mes con formato RC-001, RC-002… Lo genera el POST /ingresos y lo devuelve en la respuesta.

saldos_caja_banco

Campo Tipo Nulleable Default
id Integer PK NO
pais_id Integer FK → paises SI SET NULL
saldo_caja Numeric(15,2) NO 0
saldo_banco Numeric(15,2) NO 0
codigo_contable_caja String(20) SI
codigo_contable_banco String(20) SI
updated_at DateTime NO utcnow

codigo_contable_caja / codigo_contable_banco guardan los códigos contables de cada cuenta (ej. 11050501 Caja General, 11200501 cuenta bancaria).

traslados

Campo Tipo Nulleable Default
id Integer PK NO
pais_id Integer FK → paises SI SET NULL
de String(10) NO
a String(10) NO
valor Numeric(15,2) NO
observaciones Text SI
fecha Date NO
fecha_creacion DateTime NO utcnow

archivos

Adjuntos (PDF/imagen) asociados a un ingreso o gasto. Referencia polimórfica (tipo + referencia_id), sin FK dura porque apunta a dos tablas.

Campo Tipo Nulleable Default Notas
id Integer PK NO
tipo String(20) NO 'ingreso' | 'gasto' (CHECK)
referencia_id Integer NO id del ingreso / gasto asociado
nombre_original Text SI
content_type String(100) SI
tamano_bytes BigInteger SI
storage_path Text SI ruta interna en el bucket
url Text NO URL pública del archivo
fecha_creacion DateTime NO utcnow

Los archivos se almacenan en Supabase Storage (el disco del Space es efímero). Requiere las variables SUPABASE_URL, SUPABASE_SERVICE_KEY, SUPABASE_BUCKET; si faltan, POST /archivos responde 503.


Configuracion

configuracion

Campo Tipo Nulleable Default
id Integer PK NO
clave String(100) NO UNIQUE
valor Text NO
descripcion Text SI
fecha_actualizacion DateTime NO utcnow

Estadisticas

estadisticas_paises

Campo Tipo Nulleable Default
id Integer PK NO
nombre_pais String(100) NO
cantidad_miembros Integer SI 0
cantidad_estudios Integer SI 0
cantidad_reportes Integer SI 0
color String(20) SI
mes Integer SI
anio Integer NO
fecha_creacion DateTime SI utcnow
fecha_actualizacion DateTime SI utcnow
pais_id Integer FK → paises SI SET NULL

Endpoints de la API

Auth

/auth

Metodo Ruta Descripcion Parametros
POST /auth/login Iniciar sesion, devuelve JWT Body: email, password
GET /auth/mis-permisos Permisos del usuario autenticado Header: Authorization

El JWT incluye sub, rol y pais_id en el payload. La respuesta del login trae el objeto usuario con pais_id y pais_nombre.

Miembros

/miembros

Metodo Ruta Descripcion Parametros
GET /miembros Listar miembros ?tipo=&pais_id=
GET /miembros/{id} Obtener miembro por ID
POST /miembros Crear miembro Body: MiembroCreate
PATCH /miembros/{id} Actualizar miembro Body: MiembroUpdate
DELETE /miembros/{id} Eliminar miembro

Miembros Info Adicional

/miembros-info-adicional

Metodo Ruta Descripcion Parametros
GET /miembros-info-adicional Listar info adicional ?id=
GET /miembros-info-adicional/{id} Obtener por ID de miembro
POST /miembros-info-adicional Crear info adicional Body: MiembroInfoAdicionalCreate
PATCH /miembros-info-adicional/{id} Actualizar info adicional Body: MiembroInfoAdicionalUpdate
DELETE /miembros-info-adicional/{id} Eliminar info adicional

Contactos

/contactos

Metodo Ruta Descripcion Parametros
GET /contactos Listar contactos ?miembro_responsable_id=&pais_id=
GET /contactos/{id} Obtener contacto
POST /contactos Crear contacto Body: ContactoCreate
PATCH /contactos/{id} Actualizar contacto Body: ContactoUpdate
DELETE /contactos/{id} Eliminar contacto (409 si tiene estudios)

Estudios Diarios

/estudios-diarios

Metodo Ruta Descripcion Parametros
GET /estudios-diarios Listar estudios diarios ?miembro_id=&pais_id=&anio=&mes=
GET /estudios-diarios/{id} Obtener estudio
POST /estudios-diarios Crear estudio Body: EstudioDiarioCreate
PATCH /estudios-diarios/{id} Actualizar estudio Body: EstudioDiarioUpdate
DELETE /estudios-diarios/{id} Eliminar estudio

Reportes

/reportes

Metodo Ruta Descripcion Parametros
GET /reportes Listar reportes ?miembro_id=&pais_id=&anio=
GET /reportes/{id} Obtener reporte
POST /reportes Crear reporte Body: ReporteCreate
PATCH /reportes/{id} Actualizar reporte Body: ReporteUpdate
DELETE /reportes/{id} Eliminar reporte

Estadisticas Generales

/estadisticas

Metodo Ruta Descripcion Parametros
GET /estadisticas Dashboard: comparacion estudios, rendimiento, evangelismo, crecimiento ?anio=

Estadisticas por Pais

/estadisticas-paises

Metodo Ruta Descripcion Parametros
GET /estadisticas-paises Listar estadisticas ?pais_id=&anio=&mes=
GET /estadisticas-paises/{id} Obtener estadistica
POST /estadisticas-paises Crear estadistica Body: EstadisticaPaisCreate
PATCH /estadisticas-paises/{id} Actualizar estadistica Body: EstadisticaPaisUpdate
DELETE /estadisticas-paises/{id} Eliminar estadistica

Paises

/paises

Metodo Ruta Descripcion Parametros
GET /paises Listar paises
GET /paises/{id} Obtener pais
POST /paises Crear pais Body: PaisCreate
PATCH /paises/{id} Actualizar pais Body: PaisUpdate
DELETE /paises/{id} Eliminar pais

Continentes

/continentes

Metodo Ruta Descripcion Parametros
GET /continentes Listar continentes
GET /continentes/{id} Obtener continente
POST /continentes Crear continente Body: ContinenteCreate
PATCH /continentes/{id} Actualizar continente Body: ContinenteUpdate
DELETE /continentes/{id} Eliminar continente

Ciudades

/ciudades

Metodo Ruta Descripcion Parametros
GET /ciudades Listar ciudades ?pais_iso2=&limit=&offset=
GET /ciudades/{id} Obtener ciudad
POST /ciudades Crear ciudad Body: CiudadCreate
PATCH /ciudades/{id} Actualizar ciudad Body: CiudadUpdate
DELETE /ciudades/{id} Eliminar ciudad

Ciudades Mision

/ciudades-mision

Metodo Ruta Descripcion Parametros
GET /ciudades-mision Listar ciudades mision ?ciudad_id=&estado_presencia=
GET /ciudades-mision/{id} Obtener ciudad mision
POST /ciudades-mision Crear ciudad mision Body: CiudadMisionCreate
PATCH /ciudades-mision/{id} Actualizar ciudad mision Body: CiudadMisionUpdate
DELETE /ciudades-mision/{id} Eliminar ciudad mision

Cotizaciones

/cotizaciones

Metodo Ruta Descripcion Parametros
GET /cotizaciones Listar cotizaciones ?estado=&miembro_id=&anio=&mes=
GET /cotizaciones/{id} Obtener cotizacion
POST /cotizaciones Crear cotizacion Body: CotizacionCreate
PATCH /cotizaciones/{id} Actualizar cotizacion Body: CotizacionUpdate
DELETE /cotizaciones/{id} Eliminar cotizacion

Presupuestos

/presupuestos

Metodo Ruta Descripcion Parametros
GET /presupuestos Listar presupuestos ?pais_id=&anio=&mes=&tipo_gasto=
GET /presupuestos/{id} Obtener presupuesto
POST /presupuestos Crear presupuesto Body: PresupuestoCreate
PATCH /presupuestos/{id} Actualizar presupuesto Body: PresupuestoUpdate
DELETE /presupuestos/{id} Eliminar presupuesto

Ejecuciones

/ejecuciones

Metodo Ruta Descripcion Parametros
GET /ejecuciones Listar ejecuciones ?pais_id=&anio=&mes=
GET /ejecuciones/{id} Obtener ejecucion
POST /ejecuciones Crear ejecucion Body: EjecucionCreate
PATCH /ejecuciones/{id} Actualizar ejecucion Body: EjecucionUpdate
DELETE /ejecuciones/{id} Eliminar ejecucion

Gastos Reales

/gastos-reales

Metodo Ruta Descripcion Parametros
GET /gastos-reales Listar gastos reales ?ejecucion_id=
GET /gastos-reales/{id} Obtener gasto
POST /gastos-reales Crear gasto Body: GastoRealCreate
PATCH /gastos-reales/{id} Actualizar gasto Body: GastoRealUpdate
DELETE /gastos-reales/{id} Eliminar gasto

Ingresos

/ingresos

Metodo Ruta Descripcion Parametros
GET /ingresos Listar ingresos ?pais_id=&anio=&mes=&tipo=&donde_ingresa=
GET /ingresos/{id} Obtener ingreso
POST /ingresos Crear ingreso (genera numero RC-###) Body: IngresoCreate
PATCH /ingresos/{id} Actualizar ingreso Body: IngresoUpdate
DELETE /ingresos/{id} Eliminar ingreso

Saldos Caja / Banco

/saldos-caja-banco

Metodo Ruta Descripcion Parametros
GET /saldos-caja-banco Listar saldos ?pais_id=
GET /saldos-caja-banco/{id} Obtener saldo
POST /saldos-caja-banco Crear saldo Body: SaldoCajaBancoCreate
PATCH /saldos-caja-banco/{id} Actualizar saldo Body: SaldoCajaBancoUpdate
DELETE /saldos-caja-banco/{id} Eliminar saldo

Traslados

/traslados

Metodo Ruta Descripcion Parametros
GET /traslados Listar traslados ?pais_id=&anio=&mes=
GET /traslados/{id} Obtener traslado
POST /traslados Crear traslado Body: TrasladoCreate
PATCH /traslados/{id} Actualizar traslado Body: TrasladoUpdate
DELETE /traslados/{id} Eliminar traslado

Archivos

/archivos

Metodo Ruta Descripcion Parametros
GET /archivos Listar adjuntos ?tipo=&referencia_id=
POST /archivos Subir adjunto y asociarlo a un ingreso/gasto multipart: tipo, referencia_id, file → devuelve la URL
DELETE /archivos/{id} Eliminar adjunto

POST /archivos sube el archivo a Supabase Storage. Valida que tipo sea ingreso/gasto (422), que la referencia exista (404) y que el almacenamiento esté configurado (503).

Usuarios

/usuarios

Metodo Ruta Descripcion Parametros
GET /usuarios Listar usuarios
GET /usuarios/{id} Obtener usuario
POST /usuarios Crear usuario Body: UsuarioCreate
PATCH /usuarios/{id} Actualizar usuario Body: UsuarioUpdate
DELETE /usuarios/{id} Eliminar usuario
GET /usuarios/{id}/permisos Listar permisos
POST /usuarios/{id}/permisos Agregar permiso Body: permiso_id
PATCH /usuarios/{id}/permisos/{permiso_id} Actualizar permiso Body: tiene_acceso
DELETE /usuarios/{id}/permisos/{permiso_id} Quitar permiso

Roles y Permisos

/roles

Metodo Ruta Descripcion Parametros
GET /roles Listar roles
GET /roles/{id} Obtener rol
POST /roles Crear rol Body: RolCreate
PATCH /roles/{id} Actualizar rol Body: RolUpdate
DELETE /roles/{id} Eliminar rol
GET /roles/{rol_id}/permisos Listar permisos del rol
POST /roles/{rol_id}/permisos Agregar permiso al rol Body: permiso_id
PATCH /roles/{rol_id}/permisos/{permiso_id} Actualizar permiso del rol Body: activo
DELETE /roles/{rol_id}/permisos/{permiso_id} Quitar permiso del rol

Configuracion

/configuracion

Metodo Ruta Descripcion Parametros
GET /configuracion Listar configuracion
GET /configuracion/{clave} Obtener valor por clave
POST /configuracion Crear clave de configuracion Body: ConfiguracionCreate
PATCH /configuracion/{clave} Actualizar valor Body: ConfiguracionUpdate
DELETE /configuracion/{clave} Eliminar clave

Setup

# Variables de entorno requeridas
DATABASE_URL=postgresql://usuario:password@host:5432/neondb
SECRET_KEY=clave-secreta-para-jwt
ENVIRONMENT=development

# Almacenamiento de archivos (Supabase Storage) — para POST /archivos
SUPABASE_URL=https://TU_PROYECTO.supabase.co
SUPABASE_SERVICE_KEY=tu_service_role_key
SUPABASE_BUCKET=archivos

# Ejecutar con Docker
docker build -t gnit-api .
docker run -p 7860:7860 gnit-api

# Ejecutar localmente
pip install -r requirements.txt
uvicorn app.main:app --reload --port 7860