PROMPT DETALLADO: Sistema Web de Conteo de Votos Electorales (PHP/MySQL)
Objetivo del Prompt: Este prompt describe un sistema web completo desarrollado para registrar y contabilizar votos electorales. Incluye la descripción de la arquitectura, funcionalidades implementadas, tecnologías utilizadas, estructura de la base de datos y el código fuente completo de los archivos relevantes. Utiliza esta información como contexto para entender el sistema, responder preguntas sobre él, proponer mejoras o continuar su desarrollo.

1. Concepto General y Propósito:

El sistema es una aplicación web interna (con una página de resultados pública) para el registro manual de conteos de votos provenientes de actas electorales físicas o digitales.

Permite gestionar entidades clave como elecciones, candidatos, centros de votación (y sus mesas), y usuarios del sistema.

Su objetivo principal es digitalizar el conteo, permitir correcciones, generar reportes agregados (tabulares y gráficos) y ofrecer una vista pública de los resultados finales.

2. Tecnologías Utilizadas:

Backend: PHP (versión 8.0+ asumida por la sintaxis).

Base de Datos: MySQL / MariaDB (con estructura definida y uso de PDO para la conexión).

Frontend: HTML5, CSS3, JavaScript (Vanilla JS para funcionalidades básicas y manejo del DOM).

Framework/Librerías CSS/JS:

Bootstrap 5.3 (para layout, componentes UI y estilos base).

Font Awesome 6 (para iconos).

Chart.js 4.4 (para la generación de gráficos de barras en los reportes).

Servidor Web (Asumido): Apache o Nginx con soporte PHP (ej. XAMPP, WAMP, MAMP, o un servidor Linux).

3. Arquitectura y Estructura de Archivos:

El sistema sigue un patrón básico de Controlador Frontal (Front Controller) con index.php actuando como punto de entrada principal para el área de administración (dashboard).

VOTOS/
├── assets/
│   ├── css/
│   │   └── style.css         # Estilos CSS personalizados
│   └── js/                   # Carpeta para JS (actualmente vacía o con scripts menores)
│   └── login-bg.jpg          # Imagen de fondo para el login
├── includes/
│   └── database.php        # Clase 'Database' para conexión PDO
├── uploads/                  # Directorio para archivos subidos (FOTOS)
│   └── candidatos/           # Subdirectorio para fotos de candidatos
├── views/                    # Contiene los fragmentos de HTML/PHP para cada página
│   ├── candidatos.php
│   ├── centros_votacion.php
│   ├── dashboard_home.php
│   ├── registro_votos.php
│   ├── reporte_votos.php
│   └── usuarios.php
├── config.php                # Configuración (Credenciales BD, URLs, etc.) - NO SUBIR A GIT CON CLAVES REALES
├── export_report.php         # Script independiente para exportar reportes (CSV)
├── index.php                 # Controlador Frontal (Dashboard), Layout principal, Routing GET
├── login.php                 # Página y procesamiento de inicio de sesión
├── logout.php                # Script para cerrar sesión
├── resultado_final.php       # Página pública independiente para mostrar resultados
└── (base_datos_votos.sql)    # Archivo SQL con la estructura y datos iniciales (NO EN EL SERVIDOR)

index.php (Dashboard): Maneja el routing basado en ?page=..., verifica la sesión del usuario, incluye la navbar, la sidebar, y carga dinámicamente el archivo correspondiente de la carpeta views/ en el área de contenido. Implementa Output Buffering (ob_start/ob_end_flush) para permitir redirecciones desde los archivos incluidos. Contiene el HTML del modal de confirmación de borrado y el JS asociado. También maneja el cambio de tema claro/oscuro.

login.php: Muestra el formulario de login y procesa la autenticación contra la BD usando password_verify(). Establece variables de sesión ($_SESSION) si el login es exitoso.

logout.php: Destruye la sesión y redirige a login.php.

config.php: Define constantes PHP para las credenciales de la base de datos, URL base, directorio de subidas y ID de elección por defecto.

includes/database.php: Proporciona una clase Database con métodos estáticos connect() y disconnect() para manejar una conexión PDO Singleton.

views/*.php: Son scripts PHP/HTML que se incluyen en index.php. Contienen la lógica específica de cada sección (formularios, tablas, procesamiento POST/GET para CRUD) y acceden a la variable $pdo establecida en index.php.

resultado_final.php: Página autónoma (no usa index.php) que muestra los resultados públicamente. Incluye su propia lógica de conexión y consulta a la BD (actualmente duplicada de reporte_votos.php).

export_report.php: Script autónomo que genera un archivo CSV descargable basado en los resultados de una elección específica.

4. Estructura de la Base de Datos (votos):

(Se asume que el contenido del archivo base_datos_votos.sql proporcionado anteriormente está disponible).

elecciones: Almacena información sobre cada evento electoral (nombre, fecha, estado).

candidatos: Información de los candidatos por elección (nombre, apellido, partido, foto). Relacionada con elecciones.

centros: Catálogo de lugares físicos de votación (localidad, nombre IE).

centros_votacion: Define las mesas específicas dentro de un centro para una eleccion. Relacionada con elecciones y centros.

usuarios: Datos de los usuarios del sistema (nombre de usuario, hash de contraseña, rol, estado).

votos: Tabla principal que registra cada entrada de votos (cantidad) para un candidato en una centro_votacion (mesa) específica, realizada por un usuario en una eleccion determinada. Importante: Ya NO tiene la restricción UNIQUE para (id_eleccion, id_candidato, id_centro_votacion), permitiendo múltiples registros.

5. Funcionalidades Implementadas:

Autenticación y Sesiones:

Login seguro usando password_verify() contra hashes de BD (tabla usuarios).

Uso de session_start(), almacenamiento de user_id, username, role en $_SESSION.

Protección de páginas del dashboard (index.php) verificando $_SESSION['user_id'].

Logout (logout.php) que destruye la sesión.

Dashboard Layout Modernizado:

Navbar superior fija con título/logo y menú de usuario (perfil, salir).

Sidebar izquierda fija (debajo de navbar) con enlaces de navegación.

Área de contenido principal a la derecha.

Tema Claro/Oscuro con switch en la navbar y persistencia usando localStorage.

Gestión de Candidatos (views/candidatos.php):

Crear: Formulario para añadir nuevos candidatos (nombre, apellido, partido, foto opcional) asociados a la elección por defecto. Maneja subida de archivos de imagen (validación básica de tipo/tamaño, nombre único, movimiento a uploads/candidatos/).

Leer: Tabla que lista los candidatos de la elección actual con su foto, nombre, partido y botones de acción.

Actualizar: Formulario (el mismo de crear) se rellena con datos al hacer clic en "Editar". Permite modificar nombre, apellido, partido y reemplazar la foto. Borra la foto antigua si se sube una nueva.

Eliminar: Botón en la tabla activa modal de confirmación. Elimina el registro de la BD y el archivo de foto asociado. Impide eliminar si el candidato tiene votos registrados.

Gestión de Centros/Mesas (views/centros_votacion.php):

Crear: Formulario para añadir una nueva mesa. Busca si el centro (Localidad + Nombre IE) ya existe en centros; si no, lo crea. Luego, crea el registro de la mesa en centros_votacion para la elección actual.

Leer: Tabla que lista las mesas de la elección actual, mostrando ID, localidad, nombre IE y número de mesa.

Actualizar: Formulario permite editar únicamente el numero_mesa de un registro existente en centros_votacion. Localidad y Nombre IE se muestran como solo lectura.

Eliminar: Botón en la tabla activa modal. Elimina el registro de la tabla centros_votacion. No elimina el centro físico de la tabla centros. Impide eliminar si la mesa tiene votos registrados.

Registro/Corrección de Votos (views/registro_votos.php):

Añadir: Formulario con desplegables (cargados desde BD) para seleccionar Candidato y Mesa. Permite ingresar la cantidad de votos. Realiza un INSERT simple en la tabla votos. Permite múltiples registros para la misma combinación Candidato/Mesa.

Leer (Últimos): Tabla inferior muestra los últimos 10 registros añadidos o modificados (ordenados por updated_at DESC), mostrando ID, candidato, mesa, cantidad, usuario registrador y fechas.

Actualizar (Registro Específico): Botón "Editar" en la tabla de últimos registros carga los datos de ese registro específico en el formulario superior. Al guardar, ejecuta un UPDATE para modificar candidato, mesa o cantidad de ese registro (WHERE id = ?).

Eliminar (Registro Específico): Botón "Eliminar" en la tabla activa modal. Elimina ese registro específico de la tabla votos.

Gestión de Usuarios (views/usuarios.php - Solo Admin):

Acceso Restringido: Solo accesible por usuarios con rol 'administrador'.

Crear: Formulario para añadir nuevos usuarios (nombre usuario, contraseña + confirmación, rol, nombre completo opcional, activo/inactivo). Hash de contraseña obligatorio.

Leer: Tabla lista todos los usuarios con sus detalles y estado.

Actualizar: Permite modificar nombre de usuario, nombre completo, rol, estado. Permite establecer una nueva contraseña opcionalmente (si los campos se dejan vacíos, no cambia).

Eliminar: Botón en tabla activa modal. Impide eliminar al usuario logueado y al último administrador activo.

Reporte de Votos Interno (views/reporte_votos.php):

Realiza consulta SUM(...) GROUP BY candidato para obtener totales por candidato para la elección actual.

Muestra un gráfico de barras (Chart.js) con los resultados.

Muestra una tabla detallada con logo, nombre, partido, votos totales y porcentaje (con barra de progreso).

Exportación: Incluye botón para exportar los datos de la tabla a CSV (export_report.php).

Exportación a CSV (export_report.php):

Script independiente que recibe election_id.

Realiza la misma consulta agregada que el reporte.

Genera un archivo CSV con BOM UTF-8 y punto y coma (;) como delimitador para mejor compatibilidad con Excel.

Fuerza la descarga del archivo.

Resultados Públicos (resultado_final.php):

Página independiente (sin login) que muestra los resultados finales.

Replica la lógica de consulta y presentación (gráfico de barras horizontales + tabla) de reporte_votos.php.

6. Consideraciones de Seguridad Implementadas:

Hashing de Contraseñas: Usa password_hash() y password_verify().

Protección de Sesión: Regeneración de ID (session_regenerate_id), uso de variables de sesión para autenticación.

Consultas Preparadas (PDO): Uso extensivo de sentencias preparadas ($pdo->prepare(), $q->execute([...])) para prevenir inyección SQL.

Validación de Entradas: Uso de filter_input, trim, validaciones básicas (obligatorio, tipo entero, rol válido). htmlspecialchars() se usa para mostrar datos en HTML y prevenir XSS.

Control de Acceso por Rol: La página de usuarios está protegida para administradores.

Prevención de Eliminación Crítica: No se puede eliminar el usuario logueado ni el último admin. Se impide eliminar entidades con registros dependientes (candidatos/mesas con votos).

Lista Blanca de Páginas: index.php usa $allowed_pages para limitar los archivos que se pueden incluir.

7. Estado Actual y Limitaciones/Posibles Mejoras:

Manejo Multi-Elección: El sistema está diseñado para múltiples elecciones (BD), pero la interfaz actual asume y trabaja únicamente con DEFAULT_ELECTION_ID = 1. Falta implementar:

Interfaz para gestionar elecciones (CRUD en tabla elecciones).

Selector en el dashboard para elegir la elección activa sobre la que trabajar/ver reportes.

Pasar el id_eleccion seleccionado a las diferentes vistas y consultas.

Refactorización: La lógica de consulta y procesamiento de resultados está duplicada en reporte_votos.php, resultado_final.php, y export_report.php. Debería extraerse a una función o clase reutilizable.

Validación Robusta: La validación de entradas podría ser más exhaustiva (longitudes máximas, formatos específicos).

Seguridad Adicional: Considerar protección contra CSRF (Cross-Site Request Forgery) en los formularios. Implementar límites de intentos de login. Auditoría más detallada.

Edición/Eliminación en Tablas: Faltan implementar los botones Editar/Eliminar en algunas tablas o refinar su comportamiento (ej., ¿realmente se necesita editar una mesa o es mejor eliminarla y crearla de nuevo?).

Experiencia de Usuario (UX): Se pueden añadir DataTables.js para paginación/búsqueda en tablas largas, usar AJAX para feedback sin recargar página, mejorar diseño visual.

Manejo de Errores: Más granularidad en los mensajes de error para el usuario. Logging de errores más detallado para el desarrollador.

Gestión de Fotos: Mejorar el manejo de errores de subida, quizás permitir recortar/redimensionar.

Reportes Avanzados: Filtrar reportes por centro, localidad, etc. Diferentes tipos de gráficos.

8. Código Fuente Completo:

(Aquí se pegarían los contenidos completos de TODOS los archivos mencionados: config.php, includes/database.php, logout.php, index.php, todos los de views/, export_report.php, resultado_final.php, assets/css/style.css, y el base_datos_votos.sql)