Creación de Stored Procedures: Login e Insertar Empleado

Fecha: 18 de abril de 2026 

Hora de inicio: 12:00 a.m. 

Hora de finalización: 2:30 p.m.

Hora de inicio: 3:00 p.m. 

Hora de finalización: 5:30 p.m.

Horas trabajadas: 5h

Luego de consolidar los patrones con ListarEmplados y ListarPuestos el siguiente paso era implementar dos SPs críticos para la aplicación: Login, que maneja la autenticación y sesiones de usuarios, e InsertarEmpleado , que permite agregar nuevos empleados a la base de datos con validaciones de duplicados. Estos SPs representaron un salto en complejidad, ya que no solo devuelven datos, sino que modifican la base de datos, registran eventos en la bitácora y manejan lógica de negocio como el bloqueo por intentos fallidos.

Actividades realizadas

12:00 p.m. - 2:30 p.m.

Implementación de sp_Login

El SP de Login es uno de los más importantes, ya que es el punto de entrada a todo el sistema. Debe validar credenciales, implementar la lógica de seguridad de bloqueo por intentos fallidos, y devolver la información del usuario para mantener la sesión.

El flujo del SP es el siguiente:

1) Verificación de bloqueo por intentos fallidos: Antes de validar el username y password, se consulta la tabla BitacoraEventos para contar cuántos intentos fallidos de login ha habido en los últimos 20 minutos desde ese usuario (IP + username). Si hay 5 o más, se registra un evento de tipo 3 ("Login deshabilitado") y se devuelve el código de error 50003. Esta lógica se implementó porque el profesor indicó que después de 5 intentos fallidos en 20 minutos, el botón de login debe deshabilitarse y mostrar un mensaje al usuario.


Validación de username:
Si no hay bloqueo, se verifica que el username exista en la tabla Usuario. Si no existe, se asigna el código de error 50001 y se registra un evento de tipo 2 ("Login No Exitoso") en la bitácora con el id de usuario = 0 (ya que el usuario no existe).


Validación de password: Si el username existe pero el password es incorrecto, se asigna el código de error 50002 y se registra un evento tipo 2 en la bitácora con el id real del usuario.


Login exitoso: Si el username y password son correctos, se obtiene el id y username del usuario, se registra un evento de tipo 1 ("Login Exitoso") y se devuelve un resultset con el código 0, el id y el username.



Cada una de estas acciones (exitosa o fallida) se registra en BitacoraEvento mediante una llamada al SP de registrarBitacora , un SP creado por VB para registrar los eventos. Esto cumple con el requisito de trazabilidad: cada intento de login queda registrado para auditoría.

Implementación de InsertarEmpleado

Este SP permite insertar un nuevo empleado en la tabla Empleado. El profesor indicó que la inserción debe validarse tanto en la capa de presentación (Python/Flask) como en la capa de datos (SQL Server), de modo que incluso si algo bypasea la validación en Python, la base de datos lo rechazará.

El flujo del SP es

Validación de documento de identidad duplicado: Se verifica que no exista otro empleado activo con el mismo documento. Si existe, se asigna el código de error 50004 y se registra un evento de tipo 5 ("Inserción no exitosa") con la descripción del error.


Validación de nombre duplicado: Se verifica que no exista otro empleado activo con el mismo nombre. Si existe, se asigna el código de error 50005 y se registra un evento tipo 5 con la descripción del error.

Inserción: Si ambas validaciones pasan, se abre una transacción, se inserta el empleado con un saldo de vacaciones igual a 0 y la fecha de contratación se saca con GETDATE. Se cierra la transacción con COMMIT.

Registro de bitácora: Si la inserción fue exitosa, se registra un evento de tipo 6 ("Inserción exitosa") con los datos del empleado insertado.

Un detalle importante: las validaciones de duplicados se hacen antes de abrir la transacción. La transacción envuelve solo el INSERT y COMMIT, como indicó el profe. Esto es eficiente porque si una validación falla, no hay necesidad de abrir una transacción que luego se revertiría. Las validaciones fallidas simplemente registran el error en bitácora y usan GOTO FIN para saltar al final.

Errores encontrados

Error : La bitácora devuelve su propio resultset antes del resultCode

Al ejecutar Login desde Python, se obtenía un error indicando que pyodbc estaba leyendo un resultset inesperado o vacío.

Causa: El SP de Login llama a RegistrarBitacora en varias ocasiones. Cada vez que se llama un SP desde dentro de otro SP, ese SP devuelve su propio resultset. Entonces se recibían varios resulsets.

Sin saber cuál resultset contiene el resultCode, pyodbc termina leyendo uno de los resultsets de la bitácora que puede no tener las columnas esperadas.

Solución Encontrada: En Python, implementar un patrón de lectura que itera sobre todos los resultsets hasta encontrar el correcto.



Este patrón itera sobre todos los resultsets con cursor.nextset(), y en cada iteración verifica las columnas del resultset actual usando cursor.description. Cuando encuentra una columna llamada resultCode, sabe que encontró el resultset del SP principal y lee los datos. Luego rompe el ciclo con break.

Forma de trabajo del equipo

La comunicación fue en su mayoría por medio de whatsAPP.

Buenas prácticas descubiertas

  • Las validaciones deben ocurrir antes de las transacciones. Esto evita abrir transacciones innecesariamente. Si una validación falla, se registra el error en bitácora y se salta al final con GOTO Fin sin tocar la BD.
  • Múltiples llamadas a SPs anidados complican la lectura de resultsets en pyodbc. Cuando un SP llama a otros SPs, cada uno devuelve su propio resultset. La solución es iterar inteligentemente con cursor.nextset() y usar cursor.descriptoin para identificar el resultset correcto.
  • Las descripciones en bitácora deben incluir datos suficientes para debugging. Por ejemplo, al registrar un login fallido, se incluye el número de intentos previos y el código de error, facilitando que el profesor o desarrolladores posteriores entiendan qué ocurrió.

Referencias consultadas

Comentarios

Entradas más populares de este blog

Creación del SP de Cargar Datos

Implementación de funcionalidades: Editar Empleado y Eliminar Empleado

Implementación de funcionalidad: Consultar Empleado