Implementación de Funcionalidad: InsertarEmpleados (incluye controller, modelo y htmls)
Fecha: 22 de abril de 2026
Hora de inicio: 1:00 p.m.
Hora
de finalización: 5:00 p.m.
Horas
trabajadas: 4h
Después de
implementar la autenticación, el siguiente paso era crear la página principal
de la aplicación: el listado de empleados. Esta página es la parte principal desde el cual se puede consultar empleado,
editar, eliminar, o ver movimientos. El desafío principal fue implementar un
filtro flexible (por nombre o cédula) que se detectara automáticamente,
mantener los ids de empleados ocultos al usuario como indicaba el
requerimiento, y usar JavaScript para permitir la selección interactiva de
empleados.
Actividades realizadas
Implementación
de modelo_empleado.py
Se creó el módulo
app/model/modelo_empleado.py con funciones para operaciones sobre empleados. La
primera función implementada fue listar_empleados():
Esta función ejecuta el SP dbo.ListarEmpleados que devuelve dos resultsets: primero la lista de empleados, luego el código de resultado. El patrón es simple aquí (no hay complicaciones de bitácora intercalada como en Login). El SP devuelve exactamente dos resultsets en orden. Por eso el código usa cursor.fetchall() para obtener todas las filas del primer resultset, luego cursor.nextset() para avanzar al segundo, y finalmente cursor.fetchone()[0] para leer el código de resultado.
Los parámetros
filtro_nombre y filtro_cedula se pasan al SP como None si no hay filtro,
permitiendo que el SP busque todas los empleados. El SP internamente ejecuta
diferentes lógicas según cuál filtro sea NOT NULL.
2:00 p.m. - 3:25 p.m
Implementación
de controlador_empleado.py
Protección de
sesión:
La ruta comienza
verificando que exista una sesión activa. Si el usuario intenta acceder sin
haber hecho login, se redirige a auth.login_view. Importante porque la página de empleados no debería ser pública
Detección
automática de filtro:
El filtro viene
como query parameter en la URL (GET /empleados?filtro=603). El controlador
obtiene este valor con request.args.get('filtro', '').strip(). El .strip() elimina
espacios en blanco al inicio y final, y la cadena vacía por defecto evita
errores si no hay filtro.
Luego, se decide
automáticamente si el filtro es para cédula o nombre:
isdigit()
devuelve True solo si la cadena contiene exclusivamente dígitos 0-9. Si el
usuario ingresa "603", es cédula. Si ingresa "Perez", es
nombre. Si ingresa "603A" (mezcla), se trata como nombre (porque no
es exclusivamente dígitos).
El SP
ListarEmpleados espera recibir ambos parámetros (@inFiltroNombre y
@inFiltroCedula), pero solo uno estará lleno (el otro será NULL). El SP
internamente hace la búsqueda en la columna correcta.
Llamada al
modelo y manejo de errores:
Se llama a
listar_empleados() pasando los filtros, id del usuario y IP. Si el result_code
no es 0, se obtiene el mensaje de error de la BD mediante
obtener_mensaje_error(result_code) y se muestra con flash().
Finalmente, se
renderiza index.html pasando la lista de empleados y el filtro usado (para que
el formulario muestre lo que el usuario escribió).
3:40 p.m. - 5:00 p.m.
Implementación
de index.html
Filtro de Búsqueda
Img: form para filtro
Un formulario simple GET que envía el filtro a la misma ruta /empleados. El campo de texto tiene value="{{ filtro }}" para que se mantenga lo que el usuario escribió después de filtrar.
Tabla de empleados:
Img 5: tabla para empleados con Scroll
Estructura de
columnas:
El SP
ListarEmpleados devuelve un recordset con 6 columnas en este orden:
- emp[0]: id (no se muestra)
- emp[1]:
Nombre
- emp[2]:
ValorDocumentoIdentidad (cédula)
- emp[3]:
FechaContratacion
- emp[4]:
SaldoVacaciones
- emp[5]:
NombrePuesto
En la tabla se
muestran solo 5 columnas (sin el id), pero en el orden visual: Nombre, Cédula,
Puesto, Fecha, Saldo.
IDs ocultos al
usuario:
El requerimiento
R2 del enunciado indicó explícitamente: "La selección del empleado para
realizar alguna operación NO DEBE hacerse mediante la captura de su id. En
esta tarea los ids estarán escondidos". Por eso:
- El id (emp[0]) nunca se muestra en la
tabla
- El id viaja en el atributo
id="fila-{{ emp[0] }}" del elemento <tr>, oculto al HTML
pero accesible desde JavaScript
- El id se pasa a la función seleccionar() via el atributo onclick
Errores Encontrados
Error 1:
Código de error 50008 al filtrar
Al
intentar filtrar empleados, la aplicación devolvía error 50008 ("Error de
base de datos") sin importar el filtro.
Causa: El SP
ListarEmpleados llama a RegistrarBitacora para registrar que el usuario hizo
una consulta con filtro. RegistrarBitacora requiere que la tabla TipoEvento
tenga los registros de tipos de eventos. En ese momento, la tabla estaba vacía
porque Valeria aún no había completado su parte del script de carga XML, que
inserta los TipoEvento.
Solución
temporal: Insertar manualmente los registros de TipoEvento en SSMS mientras
Valeria terminaba su parte. Los tipos de evento requeridos son: Login Exitoso
(1), Login No Exitoso (2), Login deshabilitado (3), Logout (4), etc. Una vez
Valeria completó el script, este error desapareció.
Error 2 :Índices de columnas incorrectos en la tabla HTML
Los
datos en la tabla HTML aparecían en orden incorrecto. Por ejemplo, el puesto se
mostraba en la columna de cédula.
Causa: El SP
ListarEmpleados devuelve las columnas en un orden específico, pero el HTML las
referenciaba con índices de array incorrectos. El SP devuelve en este
orden:
- emp[0]:
id
- emp[1]:
Nombre
- emp[2]:
ValorDocumentoIdentidad
- emp[3]:
FechaContratacion
- emp[4]:
SaldoVacaciones
- emp[5]:
NombrePuesto
Pero el HTML los mapeabea bien, la solución fue simplemente mapearlos en el orden correcto.
Error 4 —
Filtro vacío causaba error
Si
el usuario no escribía nada en el filtro y presionaba "Filtrar", se
obtenía un error.
Causa: Cuando el
filtro venía vacío desde el formulario, Python pasaba un string vacío '' al SP
en lugar de None. El SP esperaba None para distinguir entre "sin
filtro" vs "filtro vacío".
Solución: Usar
.strip() para eliminar espacios, y verificar con if filtro: antes de asignar
los parámetros:
Img 6: Filtro para evitar el error
Si filtro es una cadena vacía después de .strip(), la condición if (filtro): es False, así que ambos parámetros quedan en None, y el SP devuelve todos los empleados.
Forma de trabajo del equipo
Yo (JJ) implementé modelo_empleado.py, controlador_empleado.py, index.html y la lógica de filtro/selección. Todo lo anterior en las partes relacionadas con el index.html. El tiempo más largo se dedicó a debugging de los 4 errores. La comunicación se hizo mediante whatsApp.
Referencias consultadas
- Flask
Documentation — request.args: https://flask.palletsprojects.com/en/stable/api/#flask.request.args
- Flask
Documentation — render_template: https://flask.palletsprojects.com/en/stable/
- Jinja2
Documentation — for loops: https://jinja.palletsprojects.com/en/3.0.x/
- JavaScript
— querySelectorAll: https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
- JavaScript — classList: https://developer.mozilla.org/en-
- Tarea programada 1.
- Cursor — mssql-python wiki
- Connecting to and querying SQL Server with Python
Comentarios
Publicar un comentario