Modelo de datos (referencia para mapeo)

Esta página describe las tablas y campos que usa la API web con MySQL (sql/mysql_demo.sql). Sirve para que, cuando un partido te entregue sus datos, sepas qué columnas mapear y cómo encajan provincia → municipio → recinto → colegio → personas. La app de escritorio original usa SQL Server con nombres parecidos; al vender migraciones MySQL, usa este modelo como contrato.

Jerarquía geográfica (obligatoria para la web)

provincia (id)
    └── municipio (id, id_provincia)
            └── recinto (id, municipio_id)
                    └── colegio (id_colegio, id_recinto)

padron: cada persona → id_colegio + id_provincia + (id_municipio O id_distrito_municipal según DM)
delegados_funcionarios: cada fila → colegio_id

Distrito municipal (DM): si el municipio es un DM, en municipio.descripcion suele ir texto con (DM) y descripcion_padre es el nombre del municipio “padre” para cabeceras del PDF. En padron, si aplica DM, se filtra por id_distrito_municipal; si no, por id_municipio (igual que la lógica en Database.py).

Tabla: provincia

Catálogo de provincias. La API lista con GET /provincias.

ColumnaTipoNotas para mapeo
idVARCHAR(32) PKIdentificador estable (ej. código oficial o UUID tuyo).
descripcionVARCHAR(255)Nombre visible (en la app de escritorio suele mostrarse en mayúsculas).

Tabla: municipio

ColumnaTipoNotas para mapeo
idVARCHAR(32) PKID del municipio o del distrito municipal (según tu modelo electoral).
id_provinciaVARCHAR(32) FKDebe existir en provincia.id.
descripcionVARCHAR(255)Nombre. Si es DM, conviene incluir (DM) en el texto para la lógica de cabecera/padrón.
descripcion_padreVARCHAR(255) NULLSolo útil con DM: nombre del municipio padre para el PDF.

Tabla: recinto

ColumnaTipoNotas para mapeo
idVARCHAR(32) PKID del recinto electoral.
municipio_idVARCHAR(32) FKDebe coincidir con municipio.id (en la vista sale como IdDistritoMunicipal).
codigo_recintoVARCHAR(32)Código JCE o interno.
descripcionVARCHAR(512)Nombre del recinto.
direccionVARCHAR(512)Dirección física (sale en cabecera del PDF).
estatus_recintoVARCHAR(32) NULLNULL = activo. Otro valor puede excluir el recinto de listados en SQL Server; en MySQL demo la API filtra IS NULL.

Tabla: colegio

ColumnaTipoNotas para mapeo
id_colegioVARCHAR(64) PKID único del colegio (enlace desde padron y delegados).
id_recintoVARCHAR(32) FKDebe existir en recinto.id.
descripcionVARCHAR(255)Nombre del colegio.
codigo_colegioVARCHAR(32)Código numérico o alfanumérico visible en el PDF.

Tabla: fotos_prm

ColumnaTipoNotas para mapeo
cedulaVARCHAR(20) PKMisma cédula que en padron o delegados_funcionarios.
imagenLONGBLOBBytes de la foto (JPG/PNG). Padrón usa INNER JOIN: hace falta foto para cada votante listado. Delegados: LEFT JOIN (puede faltar y usa imagen por defecto en código).

Tabla: padron (votantes para PDF “Padrón”)

Orden de columnas en SELECT coincide con el constructor Votante en Python.

ColumnaTipoNotas para mapeo
cedulaVARCHAR(20) PK11 dígitos sin guiones recomendado.
nombresVARCHAR(120)Nombre(s).
apellido1, apellido2VARCHAR(120)Apellidos.
direccion, sectorVARCHAR(255)Domicilio.
telefono, celularVARCHAR(40)Contacto.
empleadoTINYINT0 o 1.
voto2016, voto2020TINYINT0 o 1 (concurrencia en cuadro).
afprm, affpTINYINT0 o 1 (afiliación).
asistenciasocialTINYINT0 o 1.
id_provinciaVARCHAR(32) FKProvincia del votante.
id_municipioVARCHAR(32) NULLSi no es filtro DM, debe coincidir con municipio.id del municipio “normal”.
id_distrito_municipalVARCHAR(32) NULLSi el filtro es DM, rellenar con el id del registro municipio DM y dejar coherente con la consulta.
id_colegioVARCHAR(64) FKColegio donde vota.

Tabla: delegados_funcionarios (PDF “Delegados”)

El PDF coloca filas según tipo_oficio (texto en minúsculas).

ColumnaTipoNotas para mapeo
cedulaVARCHAR(20) PKCédula.
nombreVARCHAR(200)Nombre completo en un solo campo (a diferencia del padrón).
telefono, celularVARCHAR(40)Contacto.
tipo_oficioVARCHAR(80)Ver lista abajo; debe coincidir exacto (minúsculas) para el diseño del PDF.
voto2016, voto2020, asistenciasocialTINYINT0/1.
afprm, affp, empleadoTINYINT0/1.
direccion, sectorVARCHAR(255)Domicilio.
colegio_idVARCHAR(64) FKDebe ser colegio.id_colegio.

Vistas (solo lectura; las rellena el esquema)

vw_recinto_cascada

Expone: IDRecinto, CodigoRecinto, DescripcionRecinto, IdDistritoMunicipal (= municipio_id), EstatusRecinto. La API usa esta vista para listar recintos por municipio.

vw_colegio_cascada

Expone: IDColegio, CodigoColegio, codigocircunscripcion (en demo fijo 01; en producción puedes ampliar la vista o tabla para circunscripción real).

JSON para generar PDF (cuerpo POST)

La web arma este objeto desde los combos; si mapeas a mano, estos son los nombres de propiedad (snake_case):

Campo JSONOrigen típico
provinciaprovincia.id
provincia_descprovincia.descripcion
municipiomunicipio.id
municipio_descNombre para cabecera (tras lógica DM si aplica).
distrito_descNombre del distrito si es DM; si no, null o repetido según tu flujo.
recintorecinto.id
recinto_desc, recinto_codigoDescripción y código del recinto.
direccion_recintorecinto.direccion
colegiocolegio.id_colegio
colegio_desc, colegio_codigoDescripción y código del colegio.
circunscripcion_codigoDesde vista vw_colegio_cascada (demo: 01).

En Python interno estos mismos conceptos están en el diccionario colegio_a_generar (info_colegio_a_generar.py): claves provincia, provincia_desc, municipio, municipio_desc, distrito_desc, recinto, recinto_desc, recinto_codigo, direccion_recinto, colegio, colegio_desc, colegio_codigo, circunscripcion_codigo.

Valores de tipo_oficio (delegados)

El generador de PDF espera estos textos en minúsculas (compara con .lower()):

App de escritorio (SQL Server)

home.py y Database.py siguen apuntando a tablas/vistas en SQL Server (Provincia, Municipio, vwRecintoCascada, Recinto, Colegio, vwColegioCascada, Padron, delegados_funcionarios, dbPRM.dbo.FOTOS_PRM_PRM). El significado de los datos es el mismo que arriba; cambian nombres de tablas y motor. Si un cliente solo usará la web MySQL, este documento es el contrato principal.