-- Seleccionar base de datos
USE testing_votaciones;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_tarjetas_propietarios_tipos;
GO
CREATE PROCEDURE TJT.insert_update_tarjetas_propietarios_tipos
    @varPkTipo INT OUTPUT,
    @varNombre VARCHAR(100),
    @varDescripcion VARCHAR(255),
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- MAYÚSCULAS
    SET @varNombre = UPPER(@varNombre);
    SET @varDescripcion = UPPER(@varDescripcion);

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_tarjeta_propietario_tipo
    FROM TJT.tarjetas_propietarios_tipos
    WHERE nombre = @varNombre
        AND estado <> 3
        AND (@varOpc = 1 OR id_tarjeta_propietario_tipo <> @varPkTipo);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'El nombre del tipo de propietario ya existe.';
        SET @varPkTipo = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkTipo AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_tarjetas_propietarios_tipos', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.tarjetas_propietarios_tipos R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_tarjeta_propietario_tipo = @varPkTipo;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkTipo AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.tarjetas_propietarios_tipos (nombre, descripcion, creado_por)
        VALUES (@varNombre, @varDescripcion, @varUsuario);

        SET @varPkTipo = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.tarjetas_propietarios_tipos
        SET nombre = @varNombre,
            descripcion = @varDescripcion,
            modificado_por = @varUsuario
        WHERE id_tarjeta_propietario_tipo = @varPkTipo;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkTipo AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_tarjetas_tipos;
GO
CREATE PROCEDURE TJT.insert_update_tarjetas_tipos
    @varPkTipo INT OUTPUT,
    @varNombre VARCHAR(100),
    @varDescripcion VARCHAR(255),
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- MAYÚSCULAS
    SET @varNombre = UPPER(@varNombre);
    SET @varDescripcion = UPPER(@varDescripcion);

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_tarjeta_tipo
    FROM TJT.tarjetas_tipos
    WHERE nombre = @varNombre
        AND estado <> 3
        AND (@varOpc = 1 OR id_tarjeta_tipo <> @varPkTipo);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'El nombre del tipo de tarjeta ya existe.';
        SET @varPkTipo = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkTipo AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_tarjetas_tipos', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.tarjetas_tipos R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_tarjeta_tipo = @varPkTipo;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkTipo AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.tarjetas_tipos (nombre, descripcion, creado_por)
        VALUES (@varNombre, @varDescripcion, @varUsuario);

        SET @varPkTipo = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.tarjetas_tipos
        SET nombre = @varNombre,
            descripcion = @varDescripcion,
            modificado_por = @varUsuario
        WHERE id_tarjeta_tipo = @varPkTipo;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkTipo AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_bancos;
GO
CREATE PROCEDURE TJT.insert_update_bancos
    @varPkBanco INT OUTPUT,
    @varNombre VARCHAR(100),
    @varIdRegion INT,
    @varDireccion VARCHAR(255),
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- MAYÚSCULAS
    SET @varNombre = UPPER(@varNombre);
    SET @varDireccion = UPPER(@varDireccion);

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_banco
    FROM TJT.bancos
    WHERE nombre = @varNombre
        AND estado <> 3
        AND (@varOpc = 1 OR id_banco <> @varPkBanco);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'El nombre del banco ya existe.';
        SET @varPkBanco = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkBanco AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_bancos', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.bancos R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_banco = @varPkBanco;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkBanco AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.bancos (nombre, id_region, direccion, creado_por)
        VALUES (@varNombre, @varIdRegion, @varDireccion, @varUsuario);

        SET @varPkBanco = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.bancos
        SET nombre = @varNombre,
            id_region = @varIdRegion,
            direccion = @varDireccion,
            modificado_por = @varUsuario
        WHERE id_banco = @varPkBanco;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkBanco AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_tarjetas;
GO
CREATE PROCEDURE TJT.insert_update_tarjetas
    @varPkTarjeta INT OUTPUT,
    @varIdTarjetaPropietario INT,
    @varIdTarjetaPropietarioTipo INT,
    @varIdTipo INT,
    @varIdBanco INT,
    @varNumero VARCHAR(20),
    @varMesVencimiento VARCHAR(2),
    @varAnioVencimiento VARCHAR(4),
    @varCvv VARCHAR(4),
    @varTitularNombre VARCHAR(150),
    @varComentarios VARCHAR(500),
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- MAYÚSCULAS
    SET @varTitularNombre = UPPER(@varTitularNombre);
    SET @varComentarios = UPPER(@varComentarios);

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_tarjeta
    FROM TJT.tarjetas
    WHERE numero = @varNumero
        AND estado <> 3
        AND (@varOpc = 1 OR id_tarjeta <> @varPkTarjeta);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'El número de tarjeta ya existe.';
        SET @varPkTarjeta = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkTarjeta AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_tarjetas', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.tarjetas R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_tarjeta = @varPkTarjeta;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkTarjeta AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.tarjetas (
            id_tarjeta_propietario_id, id_tarjeta_propietario_tipo,
            id_tarjeta_tipo, id_banco, numero,
            mes_vencimiento, anio_vencimiento, cvv, titular_nombre,
            comentarios, creado_por
        )
        VALUES (
            @varIdTarjetaPropietario, @varIdTarjetaPropietarioTipo,
            @varIdTipo, @varIdBanco, @varNumero,
            @varMesVencimiento, @varAnioVencimiento, @varCvv, @varTitularNombre,
            @varComentarios, @varUsuario
        );

        SET @varPkTarjeta = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.tarjetas
        SET id_tarjeta_propietario_id = @varIdTarjetaPropietario,
            id_tarjeta_propietario_tipo = @varIdTarjetaPropietarioTipo,
            id_tarjeta_tipo = @varIdTipo,
            id_banco = @varIdBanco,
            numero = @varNumero,
            mes_vencimiento = @varMesVencimiento,
            anio_vencimiento = @varAnioVencimiento,
            cvv = @varCvv,
            titular_nombre = @varTitularNombre,
            comentarios = @varComentarios,
            modificado_por = @varUsuario
        WHERE id_tarjeta = @varPkTarjeta;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkTarjeta AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_empresas_empleados;
GO
CREATE PROCEDURE TJT.insert_update_empresas_empleados
    @varPkEmpleado INT OUTPUT,
    @varNombres VARCHAR(100),
    @varApellidos VARCHAR(100),
    @varIdentidad VARCHAR(20),
    @varCelular VARCHAR(20),
    @varEmail VARCHAR(100),
    @varDireccion VARCHAR(255),
    @varIdEmpresa INT,
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- MAYÚSCULAS
    SET @varNombres = UPPER(@varNombres);
    SET @varApellidos = UPPER(@varApellidos);
    SET @varDireccion = UPPER(@varDireccion);

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_empresa_empleado
    FROM TJT.empresas_empleados
    WHERE identidad = @varIdentidad
        AND estado <> 3
        AND (@varOpc = 1 OR id_empresa_empleado <> @varPkEmpleado);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'El empleado con esta identidad ya existe.';
        SET @varPkEmpleado = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkEmpleado AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_empresas_empleados', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.empresas_empleados R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_empresa_empleado = @varPkEmpleado;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkEmpleado AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.empresas_empleados (
            nombres, apellidos, identidad, celular, email,
            direccion, id_empresa, creado_por
        )
        VALUES (
            @varNombres, @varApellidos, @varIdentidad, @varCelular, @varEmail,
            @varDireccion, @varIdEmpresa, @varUsuario
        );

        SET @varPkEmpleado = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.empresas_empleados
        SET nombres = @varNombres,
            apellidos = @varApellidos,
            identidad = @varIdentidad,
            celular = @varCelular,
            email = @varEmail,
            direccion = @varDireccion,
            id_empresa = @varIdEmpresa,
            modificado_por = @varUsuario
        WHERE id_empresa_empleado = @varPkEmpleado;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkEmpleado AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_empresas_departamentos;
GO
CREATE PROCEDURE TJT.insert_update_empresas_departamentos
    @varPkDepartamento INT OUTPUT,
    @varNombre VARCHAR(100),
    @varDescripcion VARCHAR(255),
    @varIdEmpresa INT,
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- MAYÚSCULAS
    SET @varNombre = UPPER(@varNombre);
    SET @varDescripcion = UPPER(@varDescripcion);

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_empresa_departamento
    FROM TJT.empresas_departamentos
    WHERE nombre = @varNombre
        AND id_empresa = @varIdEmpresa
        AND estado <> 3
        AND (@varOpc = 1 OR id_empresa_departamento <> @varPkDepartamento);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'El nombre del departamento ya existe para esta empresa.';
        SET @varPkDepartamento = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkDepartamento AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_empresas_departamentos', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.empresas_departamentos R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_empresa_departamento = @varPkDepartamento;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkDepartamento AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.empresas_departamentos (
            nombre, descripcion, id_empresa, creado_por
        )
        VALUES (
            @varNombre, @varDescripcion, @varIdEmpresa, @varUsuario
        );

        SET @varPkDepartamento = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.empresas_departamentos
        SET nombre = @varNombre,
            descripcion = @varDescripcion,
            id_empresa = @varIdEmpresa,
            modificado_por = @varUsuario
        WHERE id_empresa_departamento = @varPkDepartamento;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkDepartamento AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_tarjetas_beneficios;
GO
CREATE PROCEDURE TJT.insert_update_tarjetas_beneficios
    @varPkBeneficio INT OUTPUT,
    @varIdTarjeta INT,
    @varNombre VARCHAR(100),
    @varDescripcion VARCHAR(255),
    @varMonto DECIMAL(18,2),
    @varTasa DECIMAL(5,2),
    @varSumaResta INT,
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- MAYÚSCULAS
    SET @varNombre = UPPER(@varNombre);
    SET @varDescripcion = UPPER(@varDescripcion);

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_tarjeta_beneficio
    FROM TJT.tarjetas_beneficios
    WHERE 
        id_tarjeta = @varIdTarjeta
        AND nombre = @varNombre
        AND estado <> 3
        AND (@varOpc = 1 OR id_tarjeta_beneficio <> @varPkBeneficio);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'El nombre del beneficio ya existe.';
        SET @varPkBeneficio = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkBeneficio AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_tarjetas_beneficios', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.tarjetas_beneficios R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_tarjeta_beneficio = @varPkBeneficio;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkBeneficio AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.tarjetas_beneficios (
            id_tarjeta, nombre, descripcion, monto, tasa, suma_o_resta, creado_por
        )
        VALUES (
            @varIdTarjeta, @varNombre, @varDescripcion, @varMonto, @varTasa, @varSumaResta, @varUsuario
        );

        SET @varPkBeneficio = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.tarjetas_beneficios
        SET 
            id_tarjeta = @varIdTarjeta,
            nombre = @varNombre,
            descripcion = @varDescripcion,
            monto = @varMonto,
            tasa = @varTasa,
            suma_o_resta = @varSumaResta,
            modificado_por = @varUsuario
        WHERE id_tarjeta_beneficio = @varPkBeneficio;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkBeneficio AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_tarjetas_intereses;
GO
CREATE PROCEDURE TJT.insert_update_tarjetas_intereses
    @varPkInteres INT OUTPUT,
    @varIdTarjeta INT,
    @varNombre VARCHAR(100),
    @varDescripcion VARCHAR(255),
    @varMonto DECIMAL(18,2),
    @varTasa DECIMAL(5,2),
    @varSumaResta INT,
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- MAYÚSCULAS
    SET @varNombre = UPPER(@varNombre);
    SET @varDescripcion = UPPER(@varDescripcion);

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_tarjeta_interes
    FROM TJT.tarjetas_intereses
    WHERE
        id_tarjeta = @varIdTarjeta
        AND nombre = @varNombre
        AND estado <> 3
        AND (@varOpc = 1 OR id_tarjeta_interes <> @varPkInteres);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'El nombre del interés ya existe.';
        SET @varPkInteres = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkInteres AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_tarjetas_intereses', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.tarjetas_intereses R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_tarjeta_interes = @varPkInteres;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkInteres AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.tarjetas_intereses (
            id_tarjeta, nombre, descripcion, monto, tasa, suma_o_resta, creado_por
        )
        VALUES (
            @varIdTarjeta, @varNombre, @varDescripcion, @varMonto, @varTasa, @varSumaResta, @varUsuario
        );

        SET @varPkInteres = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.tarjetas_intereses
        SET id_tarjeta = @varIdTarjeta,
            nombre = @varNombre,
            descripcion = @varDescripcion,
            monto = @varMonto,
            tasa = @varTasa,
            suma_o_resta = @varSumaResta,
            modificado_por = @varUsuario
        WHERE id_tarjeta_interes = @varPkInteres;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkInteres AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_cuentas;
GO
CREATE PROCEDURE TJT.insert_update_cuentas
    @varPkCuenta INT OUTPUT,
    @varCodigoContable VARCHAR(50),
    @varNombre VARCHAR(100),
    @varDescripcion VARCHAR(255),
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- MAYÚSCULAS
    SET @varCodigoContable = UPPER(@varCodigoContable);
    SET @varNombre = UPPER(@varNombre);
    SET @varDescripcion = UPPER(@varDescripcion);

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_cuenta
    FROM TJT.cuentas
    WHERE (codigo_contable = @varCodigoContable OR nombre = @varNombre)
        AND estado <> 3
        AND (@varOpc = 1 OR id_cuenta <> @varPkCuenta);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'El código contable o nombre de cuenta ya existe.';
        SET @varPkCuenta = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkCuenta AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_cuentas', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.cuentas R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_cuenta = @varPkCuenta;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkCuenta AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.cuentas (
            codigo_contable, nombre, descripcion, creado_por
        )
        VALUES (
            @varCodigoContable, @varNombre, @varDescripcion, @varUsuario
        );

        SET @varPkCuenta = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.cuentas
        SET codigo_contable = @varCodigoContable,
            nombre = @varNombre,
            descripcion = @varDescripcion,
            modificado_por = @varUsuario
        WHERE id_cuenta = @varPkCuenta;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkCuenta AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_tarjetas_gastos_categorias;
GO
CREATE PROCEDURE TJT.insert_update_tarjetas_gastos_categorias
    @varPkCategoria INT OUTPUT,
    @varNombre VARCHAR(100),
    @varDescripcion VARCHAR(255),
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- MAYÚSCULAS
    SET @varNombre = UPPER(@varNombre);
    SET @varDescripcion = UPPER(@varDescripcion);

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_tarjeta_gasto_categoria
    FROM TJT.tarjetas_gastos_categorias
    WHERE
        nombre = @varNombre
        AND creado_por = @varUsuario
        AND estado <> 3
        AND (@varOpc = 1 OR id_tarjeta_gasto_categoria <> @varPkCategoria);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'El nombre de la categoría ya existe.';
        SET @varPkCategoria = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkCategoria AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_tarjetas_gastos_categorias', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.tarjetas_gastos_categorias R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_tarjeta_gasto_categoria = @varPkCategoria;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkCategoria AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.tarjetas_gastos_categorias (
            nombre, descripcion, creado_por
        )
        VALUES (
            @varNombre, @varDescripcion, @varUsuario
        );

        SET @varPkCategoria = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.tarjetas_gastos_categorias
        SET nombre = @varNombre,
            descripcion = @varDescripcion,
            modificado_por = @varUsuario
        WHERE id_tarjeta_gasto_categoria = @varPkCategoria;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkCategoria AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_tarjetas_gastos;
GO
CREATE PROCEDURE TJT.insert_update_tarjetas_gastos
    @varPkGasto INT OUTPUT,
    @varIdTarjeta INT,
    @varIdCategoria INT,
    @varUrlFoto VARCHAR(255),
    @varMonto DECIMAL(18,2),
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_tarjetas_gastos', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.tarjetas_gastos R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_tarjeta_gasto = @varPkGasto;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkGasto AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.tarjetas_gastos (
            id_tarjeta, id_tarjeta_gasto_categoria, url_foto, monto, creado_por
        )
        VALUES (
            @varIdTarjeta, @varIdCategoria, @varUrlFoto, @varMonto, @varUsuario
        );

        SET @varPkGasto = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.tarjetas_gastos
        SET id_tarjeta = @varIdTarjeta,
            id_tarjeta_gasto_categoria = @varIdCategoria,
            url_foto = @varUrlFoto,
            monto = @varMonto,
            modificado_por = @varUsuario
        WHERE id_tarjeta_gasto = @varPkGasto;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkGasto AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_cuentas_gastos_asignaciones;
GO
CREATE PROCEDURE TJT.insert_update_cuentas_gastos_asignaciones
    @varPkAsignacion INT OUTPUT,
    @varIdCuenta INT,
    @varIdGasto INT,
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_cuenta_gasto_asignacion
    FROM TJT.cuentas_gastos_asignaciones
    WHERE id_cuenta = @varIdCuenta
        AND id_tarjeta_gasto = @varIdGasto
        AND estado <> 3
        AND (@varOpc = 1 OR id_cuenta_gasto_asignacion <> @varPkAsignacion);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'Esta asignación de cuenta ya existe para el gasto.';
        SET @varPkAsignacion = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkAsignacion AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_cuentas_gastos_asignaciones', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.cuentas_gastos_asignaciones R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_cuenta_gasto_asignacion = @varPkAsignacion;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkAsignacion AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.cuentas_gastos_asignaciones (
            id_cuenta, id_tarjeta_gasto, creado_por
        )
        VALUES (
            @varIdCuenta, @varIdGasto, @varUsuario
        );

        SET @varPkAsignacion = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.cuentas_gastos_asignaciones
        SET id_cuenta = @varIdCuenta,
            id_tarjeta_gasto = @varIdGasto,
            modificado_por = @varUsuario
        WHERE id_cuenta_gasto_asignacion = @varPkAsignacion;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkAsignacion AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_tarjetas_pagos;
GO
CREATE PROCEDURE TJT.insert_update_tarjetas_pagos
    @varPkPago INT OUTPUT,
    @varIdTarjeta INT,
    @varIdGasto INT,
    @varMonto DECIMAL(18,2),
    @varFechaHoraPago DATETIME,
    @varUrlFoto VARCHAR(255),
    @varDescripcion VARCHAR(255),
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- MAYÚSCULAS
    SET @varDescripcion = UPPER(@varDescripcion);

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_tarjetas_pagos', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.tarjetas_pagos R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_tarjeta_pago = @varPkPago;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkPago AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.tarjetas_pagos (
            id_tarjeta, id_tarjeta_gasto, monto_pagado, fecha_hora_pago, url_foto, descripcion, creado_por
        )
        VALUES (
            @varIdTarjeta, @varIdGasto, @varMonto, @varFechaHoraPago, @varUrlFoto, @varDescripcion, @varUsuario
        );

        SET @varPkPago = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.tarjetas_pagos
        SET id_tarjeta = @varIdTarjeta,
            id_tarjeta_gasto = @varIdGasto,
            monto_pagado = @varMonto,
            fecha_hora_pago = @varFechaHoraPago,
            url_foto = @varUrlFoto,
            descripcion = @varDescripcion,
            modificado_por = @varUsuario
        WHERE id_tarjeta_pago = @varPkPago;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkPago AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_presupuestos_recipientes_tipos;
GO
CREATE PROCEDURE TJT.insert_update_presupuestos_recipientes_tipos
    @varPkTipo INT OUTPUT,
    @varNombre VARCHAR(100),
    @varDescripcion VARCHAR(255),
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- MAYÚSCULAS
    SET @varNombre = UPPER(@varNombre);
    SET @varDescripcion = UPPER(@varDescripcion);

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_presupuesto_recipiente_tipo
    FROM TJT.presupuestos_recipientes_tipos
    WHERE nombre = @varNombre
        AND estado <> 3
        AND (@varOpc = 1 OR id_presupuesto_recipiente_tipo <> @varPkTipo);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'El nombre del tipo de recipiente ya existe.';
        SET @varPkTipo = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkTipo AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_presupuestos_recipientes_tipos', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.presupuestos_recipientes_tipos R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_presupuesto_recipiente_tipo = @varPkTipo;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkTipo AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.presupuestos_recipientes_tipos (
            nombre, descripcion, creado_por
        )
        VALUES (
            @varNombre, @varDescripcion, @varUsuario
        );

        SET @varPkTipo = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.presupuestos_recipientes_tipos
        SET nombre = @varNombre,
            descripcion = @varDescripcion,
            modificado_por = @varUsuario
        WHERE id_presupuesto_recipiente_tipo = @varPkTipo;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkTipo AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_presupuestos;
GO
CREATE PROCEDURE TJT.insert_update_presupuestos
    @varPkPresupuesto INT OUTPUT,
    @varIdRecipienteId INT,
    @varIdRecipienteTipo INT,
    @varMonto DECIMAL(18,2),
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0, @id_existe INT;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- VALIDAR SI YA EXISTE
    SELECT @id_existe = id_presupuesto
    FROM TJT.presupuestos
    WHERE id_presupuesto_recipiente_id = @varIdRecipienteId
        AND id_presupuesto_recipiente_tipo = @varIdRecipienteTipo
        AND estado <> 3
        AND (@varOpc = 1 OR id_presupuesto <> @varPkPresupuesto);

    IF @id_existe IS NOT NULL
    BEGIN
        SET @result = 'Ya existe un presupuesto para este recipiente.';
        SET @varPkPresupuesto = @id_existe;
        SELECT @save AS 'save', @result AS result, @varPkPresupuesto AS pk;
        RETURN;
    END;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_presupuestos', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.presupuestos R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_presupuesto = @varPkPresupuesto;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkPresupuesto AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.presupuestos (
            id_presupuesto_recipiente_id, id_presupuesto_recipiente_tipo, monto, creado_por
        )
        VALUES (
            @varIdRecipienteId, @varIdRecipienteTipo, @varMonto, @varUsuario
        );

        SET @varPkPresupuesto = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.presupuestos
        SET id_presupuesto_recipiente_id = @varIdRecipienteId,
            id_presupuesto_recipiente_tipo = @varIdRecipienteTipo,
            monto = @varMonto,
            modificado_por = @varUsuario
        WHERE id_presupuesto = @varPkPresupuesto;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkPresupuesto AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_update_backups;
GO
CREATE PROCEDURE TJT.insert_update_backups
    @varPkBackup INT OUTPUT,
    @varTipo VARCHAR(20),
    @varEstatus VARCHAR(20),
    @varEstatusComentario TEXT,
    @varTamanoMb DECIMAL(10,2),
    @varHashVerificacion TEXT,
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_backups', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.backups R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_backup = @varPkBackup;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkBackup AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        INSERT INTO TJT.backups (
            backup_tipo, estatus, estatus_comentario, tamano_mb, hash_verificacion, creado_por
        )
        VALUES (
            @varTipo, @varEstatus, @varEstatusComentario, @varTamanoMb, @varHashVerificacion, @varUsuario
        );

        SET @varPkBackup = SCOPE_IDENTITY();
        SET @save = 1;
        SET @result = 'Registro insertado correctamente';
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.backups
        SET backup_tipo = @varTipo,
            estatus = @varEstatus,
            estatus_comentario = @varEstatusComentario,
            tamano_mb = @varTamanoMb,
            hash_verificacion = @varHashVerificacion,
            modificado_por = @varUsuario
        WHERE id_backup = @varPkBackup;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkBackup AS pk;
END;
GO





DROP PROCEDURE IF EXISTS TJT.insert_audit_log;
GO
CREATE PROCEDURE TJT.insert_audit_log
    @varUsuario VARCHAR(100),
    @varEntidadAfectada VARCHAR(100),
    @varIdEntidad INT,
    @varAccion VARCHAR(20),
    @varIpOrigen VARCHAR(50),
    @varDispositivo VARCHAR(255),
    @varPkLog INT OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0;

    -- MAYÚSCULAS
    SET @varEntidadAfectada = UPPER(@varEntidadAfectada);
    SET @varAccion = UPPER(@varAccion);
    SET @varDispositivo = UPPER(@varDispositivo);

    INSERT INTO TJT.audit_log (
        usuario, entidad_afectada, id_entidad, accion,
        ip_origen, dispositivo
    )
    VALUES (
        @varUsuario, @varEntidadAfectada, @varIdEntidad, @varAccion,
        @varIpOrigen, @varDispositivo
    );

    SET @varPkLog = SCOPE_IDENTITY();
    SET @save = 1;
    SET @result = 'Registro de auditoría creado correctamente';

    SELECT @save AS 'save', @result AS result, @varPkLog AS pk;
END;
GO




DROP PROCEDURE IF EXISTS TJT.insert_update_aichat_mensajes;
GO
CREATE PROCEDURE TJT.insert_update_aichat_mensajes
    @varPkMensaje INT OUTPUT,
    @varMensaje VARCHAR(MAX),
    @varSesion INT,
    @varIdUsuario INT,
    @varUsuario VARCHAR(100),
    @varOpc INT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @result NVARCHAR(200), @save INT = 0;
    DECLARE @acceso_todos INT, @acceso_empresa INT, @acceso_propio INT, @id_usuario INT, @id_empresa INT;
    DECLARE @usuario_propietario VARCHAR(100), @empresa_propietario INT;

    -- Obtener permisos del usuario
    EXEC especializadas_seguridad.dbo.obtain_permisos_usuario @varUsuario = @varUsuario, @varCodigoPermiso = 'save_aichat_mensajes', @varIdModulo = 3, @id_usuario = @id_usuario OUTPUT, @id_empresa = @id_empresa OUTPUT, @acceso_todos = @acceso_todos OUTPUT, @acceso_empresa = @acceso_empresa OUTPUT, @acceso_propio = @acceso_propio OUTPUT;

    -- Para actualización: verificar permisos sobre el registro existente
    IF @varOpc = 2
    BEGIN
        SELECT @usuario_propietario = R.creado_por, @empresa_propietario = U.id_empresa
        FROM TJT.aichat_mensajes R
        LEFT JOIN especializadas_seguridad.dbo.usuarios U ON R.creado_por = U.usuario
        WHERE R.id_mensaje = @varPkMensaje;

        IF NOT (
            @acceso_todos = 1
            OR (@acceso_empresa = 1 AND @empresa_propietario = @id_empresa)
            OR (@acceso_propio = 1 AND @usuario_propietario = @varUsuario)
        )
        BEGIN
            SET @result = 'No tiene permisos para modificar este registro';
            SELECT @save AS 'save', @result AS result, @varPkMensaje AS pk;
            RETURN;
        END;
    END;

    IF @varOpc = 1 -- INSERTAR
    BEGIN
        -- Verificar si el usuario ya tiene 10 mensajes hoy
        IF (
            SELECT COUNT(1)
            FROM TJT.aichat_mensajes
            WHERE 
                id_usuario = @varIdUsuario
                AND CAST(fecha_hora_creado AS DATE) = CAST(GETDATE() AS DATE)
        ) >= 10
        BEGIN
            SET @save = 0;
            SET @result = 'Lo siento. ¡Has alcanzado el límite de mensajes por hoy!' 
             + CHAR(13) + CHAR(10) 
             + 'Recuerda que tienes un máximo de 10 interacciones diarias.';

        END;
        ELSE
        BEGIN
            INSERT INTO TJT.aichat_mensajes (
                mensaje, sesion, id_usuario, creado_por
            )
            VALUES (
                @varMensaje, @varSesion, @varIdUsuario, @varUsuario
            );

            SET @varPkMensaje = SCOPE_IDENTITY();
            SET @save = 1;
            SET @result = 'Registro insertado correctamente';
        END;
    END;
    ELSE IF @varOpc = 2 -- ACTUALIZAR
    BEGIN
        UPDATE TJT.aichat_mensajes
        SET mensaje = @varMensaje,
            sesion = @varSesion,
            id_usuario = @varIdUsuario,
            modificado_por = @varUsuario
        WHERE id_mensaje = @varPkMensaje;

        SET @save = 1;
        SET @result = 'Registro actualizado correctamente';
    END;
    ELSE
    BEGIN
        SET @result = 'Opción no válida';
    END;

    SELECT @save AS 'save', @result AS result, @varPkMensaje AS pk;
END;
GO
