Entrada 6 (SP getEmpledos)

# Bitácora de Sesión

 Fecha: 22/04/2026

 Inicio: [20:00] | Fin: [22:00] || Total: [2 horas]

 Presentes: Matías Benavides Sandoval

 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

¿QUÉ HICIMOS HOY?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

- Se completó y validó el SP de listado con filtro: sp_GetEmpleados.

- Se ajustó la lógica de normalización y clasificación del filtro para cumplir la especificación:

    - vacío o espacios -> todos

    - solo números -> cédula

    - letras/espacios -> nombre

- Se incorporó bitácora para consultas por filtro de nombre y cédula.

- Se cambió la búsqueda por cédula a búsqueda aproximada con LIKE

- Se hicieron pruebas reales para los casos: vacío, nombre, cédula y mixto.

- Se estandarizaron TODOS los SPs del proyecto con convención de parámetros in/out y con un solo DECLARE por SP.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

PROBLEMAS ENCONTRADOS Y CÓMO SE RESOLVIERON

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

1) Error: Invalid column name IdTipoEvento

- Causa: en TipoEvento la PK real es id, no IdTipoEvento.

- Antes:

    SELECT @idTipoEventoNombre = IdTipoEvento FROM TipoEvento WHERE Nombre = 'Consulta con filtro de nombre';

- Después:

    SELECT @idTipoEventoNombre = id FROM TipoEvento WHERE Nombre = 'Consulta con filtro de nombre';

 

2) Error: Invalid column name Activo

- Causa: la columna correcta en Empleado es EsActivo.

- Antes:

    WHERE Activo = 1

- Después:

    WHERE EsActivo = 1

 

3) Error: Incorrect syntax near WHERE

- Causa: en el SELECT del filtro nombre había dos WHERE consecutivos.

- Antes:

    WHERE (Nombre LIKE ...)

    WHERE EsActivo = 1

- Después:

    WHERE (Nombre LIKE ...)

        AND EsActivo = 1

 

4) Error al recompilar sp_InsertarEmpleado tras refactor masivo

- Mensaje observado: Invalid column name 'FechaContrataci(aca aparecia un simbolo raro)n'

- Causa: tema de codificación/acento al referenciar explícitamente la columna con tilde durante el refactor.

- Antes:

    INSERT INTO Empleado (idPuesto, ValorDocumentoIdentidad, Nombre, [FechaContratación], SaldoVacaciones, EsActivo)

    VALUES (...)

- Después:

    INSERT INTO Empleado

    VALUES (@inIdPuesto, @inValorDocumentoIdentidad, @inNombre, CAST(GETDATE() AS DATE), 0.00, 1);

- Resultado: recompilación exitosa.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

DUDAS Y DIVERGENCIAS DE CRITERIO

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

- Se confirmó con especificación que la búsqueda por cédula debe ser aproximada, no exacta.

- Se decidió fallback para filtro mixto (ejemplo A1): tratar como nombre para no bloquear al usuario.

- Se confirmó que la trazabilidad en este módulo usa dos tipos de evento:

    - Consulta con filtro de nombre

    - Consulta con filtro de cedula

 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

AVANCE DEL CÓDIGO

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

USE VacacionesDB;
GO
-- =====================================================
-- SP 4: Obtener lista de empleados
-- =====================================================
DROP PROCEDURE IF EXISTS sp_GetEmpleados;
GO

CREATE PROCEDURE sp_GetEmpleados
    @outResultCode INT OUTPUT,
    @inFiltro VARCHAR(128) = NULL,
    @inUsername VARCHAR(128) = NULL,
    @inIpPostIn VARCHAR(64) = NULL,
    @inPostTime DATETIME = NULL
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @filtroNomvbrePuesto VARCHAR(128),
            @tipoFiltro VARCHAR(32),
            @idUsuario INT,
            @idTipoEventoNombre INT,
            @idTipoEventoCedula INT;

    BEGIN TRY
        -- Normalizar
        SET @filtroNomvbrePuesto = LTRIM(RTRIM(ISNULL(@inFiltro, '')));
        SET @filtroNomvbrePuesto = UPPER(@filtroNomvbrePuesto);

        -- Clasificar filtro
        IF @filtroNomvbrePuesto = ''
            SET @tipoFiltro = 'TODOS';
        ELSE IF PATINDEX('%[^0-9]%', @filtroNomvbrePuesto) = 0
            SET @tipoFiltro = 'CEDULA';
        ELSE IF PATINDEX('%[^A-Z ]%', @filtroNomvbrePuesto) = 0
            SET @tipoFiltro = 'NOMBRE_PUESTO';
        ELSE
            SET @tipoFiltro = 'NOMBRE_PUESTO';
       
        -- Obtener usuario
        SELECT @idUsuario = Id FROM [dbo].[Usuario] WHERE Username = @inUsername;

        -- Obtener tipos de eventos
        SELECT @idTipoEventoNombre = id
        FROM [dbo].[TipoEvento]
        WHERE Nombre = 'Consulta con filtro de nombre';

        SELECT @idTipoEventoCedula = Id
        FROM [dbo].[TipoEvento]
        WHERE Nombre = 'Consulta con filtro de cedula';

        -- Log evento
        IF @tipoFiltro = 'NOMBRE_PUESTO'
        BEGIN
            INSERT INTO [dbo].[BitacoraEvento] (IdUsuario, IdTipoEvento, Descripcion, IpPostIn, PostTime)
            VALUES (@idUsuario, @idTipoEventoNombre, @filtroNomvbrePuesto, @inIpPostIn, @inPostTime);
        END
        ELSE IF @tipoFiltro = 'CEDULA'
        BEGIN
            INSERT INTO [dbo].[BitacoraEvento] (IdUsuario, IdTipoEvento, Descripcion, IpPostIn, PostTime)
            VALUES (@idUsuario, @idTipoEventoCedula, @filtroNomvbrePuesto, @inIpPostIn, @inPostTime);
        END

                -- Obtener empleados
        IF @tipoFiltro = 'NOMBRE_PUESTO'
            SELECT Id, Nombre, ValorDocumentoIdentidad, idPuesto FROM [dbo].[Empleado]
            WHERE (Nombre LIKE '%' + @filtroNomvbrePuesto + '%' OR
                    idPuesto IN (
                        SELECT Id
                        FROM [dbo].[Puesto]
                        WHERE Nombre LIKE '%' + @filtroNomvbrePuesto + '%'))
            AND EsActivo = 1
            ORDER BY Nombre ASC;
       
        ELSE IF @tipoFiltro = 'CEDULA'
            SELECT Id, Nombre, ValorDocumentoIdentidad, idPuesto FROM [dbo].[Empleado]
            WHERE ValorDocumentoIdentidad LIKE '%' + @filtroNomvbrePuesto + '%'
            AND EsActivo = 1
            ORDER BY Nombre ASC;
       
        ELSE IF @tipoFiltro = 'TODOS'
            SELECT Id, Nombre, ValorDocumentoIdentidad, idPuesto FROM [dbo].[Empleado]
            WHERE EsActivo = 1
            ORDER BY Nombre ASC;
       
        SET @outResultCode = 0;
    END TRY
    BEGIN CATCH
        INSERT INTO DBError (UserName, Number, State, Severity, Line, [Procedure], Message, DateTime)
        VALUES (
            ISNULL(@inUsername, SYSTEM_USER),
            ERROR_NUMBER(),
            CAST(ERROR_STATE() AS VARCHAR(32)),
            CAST(ERROR_SEVERITY() AS VARCHAR(32)),
            ERROR_LINE(),
            ISNULL(ERROR_PROCEDURE(), 'sp_GetEmpleados'),
            ERROR_MESSAGE(),
            GETDATE()
        );
        SET @outResultCode = 50008;
    END CATCH
END;
USE VacacionesDB;
GO
-- =====================================================
-- SP 4: Obtener lista de empleados
-- =====================================================
DROP PROCEDURE IF EXISTS sp_GetEmpleados;
GO

CREATE PROCEDURE sp_GetEmpleados
    @outResultCode INT OUTPUT,
    @inFiltro VARCHAR(128) = NULL,
    @inUsername VARCHAR(128) = NULL,
    @inIpPostIn VARCHAR(64) = NULL,
    @inPostTime DATETIME = NULL
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @filtroNomvbrePuesto VARCHAR(128),
            @tipoFiltro VARCHAR(32),
            @idUsuario INT,
            @idTipoEventoNombre INT,
            @idTipoEventoCedula INT;

    BEGIN TRY
        -- Normalizar
        SET @filtroNomvbrePuesto = LTRIM(RTRIM(ISNULL(@inFiltro, '')));
        SET @filtroNomvbrePuesto = UPPER(@filtroNomvbrePuesto);

        -- Clasificar filtro
        IF @filtroNomvbrePuesto = ''
            SET @tipoFiltro = 'TODOS';
        ELSE IF PATINDEX('%[^0-9]%', @filtroNomvbrePuesto) = 0
            SET @tipoFiltro = 'CEDULA';
        ELSE IF PATINDEX('%[^A-Z ]%', @filtroNomvbrePuesto) = 0
            SET @tipoFiltro = 'NOMBRE_PUESTO';
        ELSE
            SET @tipoFiltro = 'NOMBRE_PUESTO';
       
        -- Obtener usuario
        SELECT @idUsuario = Id FROM [dbo].[Usuario] WHERE Username = @inUsername;

        -- Obtener tipos de eventos
        SELECT @idTipoEventoNombre = id
        FROM [dbo].[TipoEvento]
        WHERE Nombre = 'Consulta con filtro de nombre';

        SELECT @idTipoEventoCedula = Id
        FROM [dbo].[TipoEvento]
        WHERE Nombre = 'Consulta con filtro de cedula';

        -- Log evento
        IF @tipoFiltro = 'NOMBRE_PUESTO'
        BEGIN
            INSERT INTO [dbo].[BitacoraEvento] (IdUsuario, IdTipoEvento, Descripcion, IpPostIn, PostTime)
            VALUES (@idUsuario, @idTipoEventoNombre, @filtroNomvbrePuesto, @inIpPostIn, @inPostTime);
        END
        ELSE IF @tipoFiltro = 'CEDULA'
        BEGIN
            INSERT INTO [dbo].[BitacoraEvento] (IdUsuario, IdTipoEvento, Descripcion, IpPostIn, PostTime)
            VALUES (@idUsuario, @idTipoEventoCedula, @filtroNomvbrePuesto, @inIpPostIn, @inPostTime);
        END

                -- Obtener empleados
        IF @tipoFiltro = 'NOMBRE_PUESTO'
            SELECT Id, Nombre, ValorDocumentoIdentidad, idPuesto FROM [dbo].[Empleado]
            WHERE (Nombre LIKE '%' + @filtroNomvbrePuesto + '%' OR
                    idPuesto IN (
                        SELECT Id
                        FROM [dbo].[Puesto]
                        WHERE Nombre LIKE '%' + @filtroNomvbrePuesto + '%'))
            AND EsActivo = 1
            ORDER BY Nombre ASC;
       
        ELSE IF @tipoFiltro = 'CEDULA'
            SELECT Id, Nombre, ValorDocumentoIdentidad, idPuesto FROM [dbo].[Empleado]
            WHERE ValorDocumentoIdentidad LIKE '%' + @filtroNomvbrePuesto + '%'
            AND EsActivo = 1
            ORDER BY Nombre ASC;
       
        ELSE IF @tipoFiltro = 'TODOS'
            SELECT Id, Nombre, ValorDocumentoIdentidad, idPuesto FROM [dbo].[Empleado]
            WHERE EsActivo = 1
            ORDER BY Nombre ASC;
       
        SET @outResultCode = 0;
    END TRY
    BEGIN CATCH
        INSERT INTO DBError (UserName, Number, State, Severity, Line, [Procedure], Message, DateTime)
        VALUES (
            ISNULL(@inUsername, SYSTEM_USER),
            ERROR_NUMBER(),
            CAST(ERROR_STATE() AS VARCHAR(32)),
            CAST(ERROR_SEVERITY() AS VARCHAR(32)),
            ERROR_LINE(),
            ISNULL(ERROR_PROCEDURE(), 'sp_GetEmpleados'),
            ERROR_MESSAGE(),
            GETDATE()
        );
        SET @outResultCode = 50008;
    END CATCH
END;

 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

MORALEJAS / BUENAS PRÁCTICAS

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

- Revisar nombres reales de columnas.

- Evitar hardcodear ids de eventos, resolver por Nombre en TipoEvento.

- Mantener consistencia de parámetros in/out.

- Probar siempre con casos funcionales reales y también casos borde.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

PRÓXIMA SESIÓN: ¿QUÉ SIGUE?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

- Empezar: implementar endpoint GET /api/empleados que llame sp_GetEmpleados.

- Luego conectar la pantalla de listado/filtro con ese endpoint.

 

 

Comentarios

Entradas más populares de este blog

Entrada 16 (Controlador de movimientos)

Entrada 20 (Lógica de insertarMovimientos, conectarla y probarla)

Entrada 21 (Análisis de resultados)