-- Seleccionar base de datos
USE seg_nexapps;
GO


-- DROP PROCEDURE IF EXISTS dbo.obtain_permisos_usuario;
-- GO
-- CREATE PROCEDURE dbo.obtain_permisos_usuario
--     @varUsuario VARCHAR(50),
--     @varIdModulo INT,
--     @varCodigoPermiso VARCHAR(50),
--     @acceso_todos INT OUTPUT,
--     @acceso_empresa INT OUTPUT,
--     @acceso_propio INT OUTPUT,
--     @id_usuario INT OUTPUT,
--     @id_empresa INT OUTPUT
-- AS
-- BEGIN
--     SET NOCOUNT ON;
    
--     -- Datos del usuario
--     DECLARE @id_rol_solicitante INT;
    
--     SELECT 
--         @id_usuario = id_usuario,
--         @id_empresa = id_empresa
--     FROM dbo.usuarios 
--     WHERE usuario = @varUsuario;

--     -- SELECT
--     --     @id_rol_solicitante = id_rol
--     -- FROM usuarios_roles_asignados
--     -- WHERE id_usuario = @id_usuario
--     --     AND (SELECT URT.id_modulo FROM usuarios_roles_tipos URT WHERE URT.id_rol = id_rol) = @varIdModulo; 

--     SELECT TOP 1
--         @id_rol_solicitante = usuario_rol_asignacion.id_rol
--     FROM usuarios_roles_asignados usuario_rol_asignacion
--     JOIN usuarios_roles_tipos usuario_rol_tipo ON usuario_rol_tipo.id_rol = usuario_rol_asignacion.id_rol
--     WHERE usuario_rol_asignacion.id_usuario = @id_usuario
--     AND usuario_rol_tipo.id_modulo = @varIdModulo;

    
--     -- Inicializar flags de permisos
--     DECLARE @permiso_todos_rol INT = 0;
--     DECLARE @permiso_empresa_rol INT = 0;
--     DECLARE @permiso_propio_rol INT = 0;

--     DECLARE @permiso_todos_usuario INT = 0;
--     DECLARE @permiso_empresa_usuario INT = 0;
--     DECLARE @permiso_propio_usuario INT = 0;

--     -- Permisos por ROL
--     SELECT 
--         @permiso_todos_rol = MAX(CASE WHEN permiso.codigo = @varCodigoPermiso THEN 1 ELSE 0 END),
--         @permiso_empresa_rol = MAX(CASE WHEN permiso.codigo = CONCAT(@varCodigoPermiso, '__empresa') THEN 1 ELSE 0 END),
--         @permiso_propio_rol = MAX(CASE WHEN permiso.codigo = CONCAT(@varCodigoPermiso, '__propio') THEN 1 ELSE 0 END)
--     FROM dbo.roles_permisos_asignaciones rol_permiso_asignacion
--     JOIN dbo.modulos_permisos permiso ON rol_permiso_asignacion.id_permiso = permiso.id_permiso
--     WHERE rol_permiso_asignacion.estado <> 3
--     AND rol_permiso_asignacion.id_rol = @id_rol_solicitante
--     AND permiso.codigo IN (
--         @varCodigoPermiso, 
--         CONCAT(@varCodigoPermiso, '__empresa'), 
--         CONCAT(@varCodigoPermiso, '__propio')
--     )
--     AND permiso.id_modulo = @varIdModulo
--     ;

--     -- Permisos por USUARIO DIRECTO
--     SELECT 
--         @permiso_todos_usuario = MAX(CASE WHEN permiso.codigo = @varCodigoPermiso THEN 1 ELSE NULL END),
--         @permiso_empresa_usuario = MAX(CASE WHEN permiso.codigo = CONCAT(@varCodigoPermiso, '__empresa') THEN 1 ELSE NULL END),
--         @permiso_propio_usuario = MAX(CASE WHEN permiso.codigo = CONCAT(@varCodigoPermiso, '__propio') THEN 1 ELSE NULL END)
--     FROM dbo.usuarios_permisos_asignaciones usuario_permiso_asignacion
--     JOIN dbo.modulos_permisos permiso ON usuario_permiso_asignacion.id_permiso = permiso.id_permiso
--     WHERE usuario_permiso_asignacion.estado <> 3
--     AND usuario_permiso_asignacion.id_usuario = @id_usuario
--     AND permiso.codigo IN (
--         @varCodigoPermiso,
--         CONCAT(@varCodigoPermiso, '__empresa'),
--         CONCAT(@varCodigoPermiso, '__propio')
--     )
--     AND permiso.id_modulo = @varIdModulo
--     ;

--     -- Resultado final: si hay directo, usa directo; si no hay, usa rol
--     -- DECLARE @acceso_todos INT = ISNULL(@permiso_todos_usuario, @permiso_todos_rol);
--     -- DECLARE @acceso_empresa INT = ISNULL(@permiso_empresa_usuario, @permiso_empresa_rol);
--     -- DECLARE @acceso_propio INT = ISNULL(@permiso_propio_usuario, @permiso_propio_rol);

--     -- Aquí puedes devolverlos o usarlos como necesites
--     -- SELECT 
--     --     @acceso_todos AS todos,
--     --     @acceso_empresa AS empresa,
--     --     @acceso_propio AS propio;

--     SET @acceso_todos = ISNULL(@permiso_todos_usuario, @permiso_todos_rol);
--     SET @acceso_empresa = ISNULL(@permiso_empresa_usuario, @permiso_empresa_rol);
--     SET @acceso_propio = ISNULL(@permiso_propio_usuario, @permiso_propio_rol);
-- END;
-- GO

-- EXEC obtain_permisos_usuario
--     @varUsuario = 'SERGICAST02'
--     ,@varCodigoPermiso = 'save_tarjeta_propietario'
--     ,@varIdModulo = 3
--     ,@acceso_todos = NULL
--     ,@acceso_empresa = NULL
--     ,@acceso_propio = NULL
--     ,@id_usuario = NULL
--     ,@id_empresa = NULL
--     ;


DROP FUNCTION IF EXISTS dbo.fn_obtain_permisos_usuario;
GO
CREATE FUNCTION dbo.fn_obtain_permisos_usuario(
    @varUsuario VARCHAR(50),
    @varIdModulo INT,
    @varCodigoPermiso VARCHAR(50)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @acceso_todos INT
            , @acceso_empresa INT
            , @acceso_propio INT
            
            , @id_usuario INT
            , @id_empresa INT
            , @id_rol_solicitante INT
            
            , @permiso_todos_rol INT = 0
            , @permiso_empresa_rol INT = 0
            , @permiso_propio_rol INT = 0

            , @permiso_todos_usuario INT = 0
            , @permiso_empresa_usuario INT = 0
            , @permiso_propio_usuario INT = 0

            ;

    
    -- Datos del usuario
    SELECT 
        @id_usuario = id_usuario,
        @id_empresa = id_empresa
    FROM dbo.usuarios 
    WHERE usuario = @varUsuario;

    SELECT TOP 1
        @id_rol_solicitante = usuario_rol_asignacion.id_rol
    FROM usuarios_roles_asignados usuario_rol_asignacion
    JOIN usuarios_roles_tipos usuario_rol_tipo ON usuario_rol_tipo.id_rol = usuario_rol_asignacion.id_rol
    WHERE usuario_rol_asignacion.id_usuario = @id_usuario
    AND usuario_rol_tipo.id_modulo = @varIdModulo;


    -- Permisos por ROL
    SELECT 
        @permiso_todos_rol = MAX(CASE WHEN permiso.codigo = @varCodigoPermiso THEN 1 ELSE 0 END)
        , @permiso_empresa_rol = MAX(CASE WHEN permiso.codigo = CONCAT(@varCodigoPermiso, '__empresa') THEN 1 ELSE 0 END)
        , @permiso_propio_rol = MAX(CASE WHEN permiso.codigo = CONCAT(@varCodigoPermiso, '__propio') THEN 1 ELSE 0 END)
    FROM dbo.roles_permisos_asignaciones rol_permiso_asignacion
    JOIN dbo.modulos_permisos permiso ON rol_permiso_asignacion.id_permiso = permiso.id_permiso
    WHERE rol_permiso_asignacion.estado <> 3
    AND rol_permiso_asignacion.id_rol = @id_rol_solicitante
    AND permiso.codigo IN (
        @varCodigoPermiso
        , CONCAT(@varCodigoPermiso, '__empresa')
        , CONCAT(@varCodigoPermiso, '__propio')
    )
    AND permiso.id_modulo = @varIdModulo
    ;

    -- Permisos por USUARIO DIRECTO
    SELECT 
        @permiso_todos_usuario = MAX(CASE WHEN permiso.codigo = @varCodigoPermiso THEN 1 ELSE NULL END)
        , @permiso_empresa_usuario = MAX(CASE WHEN permiso.codigo = CONCAT(@varCodigoPermiso, '__empresa') THEN 1 ELSE NULL END)
        , @permiso_propio_usuario = MAX(CASE WHEN permiso.codigo = CONCAT(@varCodigoPermiso, '__propio') THEN 1 ELSE NULL END)
    FROM dbo.usuarios_permisos_asignaciones usuario_permiso_asignacion
    JOIN dbo.modulos_permisos permiso ON usuario_permiso_asignacion.id_permiso = permiso.id_permiso
    WHERE usuario_permiso_asignacion.estado <> 3
    AND usuario_permiso_asignacion.id_usuario = @id_usuario
    AND permiso.codigo IN (
        @varCodigoPermiso
        , CONCAT(@varCodigoPermiso, '__empresa')
        , CONCAT(@varCodigoPermiso, '__propio')
    )
    AND permiso.id_modulo = @varIdModulo
    ;
    

    --
    SET @acceso_todos = ISNULL(@permiso_todos_usuario, @permiso_todos_rol);
    SET @acceso_empresa = ISNULL(@permiso_empresa_usuario, @permiso_empresa_rol);
    SET @acceso_propio = ISNULL(@permiso_propio_usuario, @permiso_propio_rol);


    --
    DECLARE @json NVARCHAR(MAX);

    SELECT @json = (
        SELECT @acceso_todos AS acceso_todos
                , @acceso_empresa AS acceso_empresa
                , @acceso_propio AS acceso_propio
                , @id_usuario AS id_usuario
                , @id_empresa AS id_empresa
                
        FOR JSON PATH
        , WITHOUT_ARRAY_WRAPPER
    )
    ;

    IF @json IS NULL
        SET @json = N'{}';

    RETURN @json;
END;
GO








DROP PROCEDURE IF EXISTS dbo.obtain_usuario_has_menu;
GO
CREATE PROCEDURE dbo.obtain_usuario_has_menu
    @varUsuario VARCHAR(50),
    @varIdModulo INT,
    @varCodigoMenu VARCHAR(50)
AS
BEGIN
    SET NOCOUNT ON;
    
    -- Datos del usuario
    DECLARE @id_usuario INT;
    DECLARE @id_rol_solicitante INT;
    
    SELECT 
        @id_usuario = id_usuario
    FROM dbo.usuarios 
    WHERE usuario = @varUsuario;


    SELECT TOP 1
        @id_rol_solicitante = usuario_rol_asignacion.id_rol
    FROM usuarios_roles_asignados usuario_rol_asignacion
    JOIN usuarios_roles_tipos usuario_rol_tipo ON usuario_rol_tipo.id_rol = usuario_rol_asignacion.id_rol
    WHERE usuario_rol_asignacion.id_usuario = @id_usuario
    AND usuario_rol_tipo.id_modulo = @varIdModulo;

    
    -- Inicializar flags de menus
    DECLARE @menu_rol INT = 0;
    DECLARE @menu_usuario INT = 0;

    -- Menus por ROL
    SELECT 
        @menu_rol = CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END
    FROM dbo.menus_roles rol_menu_asignacion
    JOIN dbo.menus menu ON rol_menu_asignacion.id_menu = menu.id_menu
    -- si tiene estos 3 existe la asignacion del MENU AL ROL
    WHERE
    -- rol_menu_asignacion.estado <> 3 -- no tiene campo estado
    rol_menu_asignacion.id_rol = @id_rol_solicitante
    AND menu.codigo_menu = @varCodigoMenu
    AND menu.id_modulo = @varIdModulo
    ;

    -- Menus por USUARIO DIRECTO
    SELECT 
        @menu_usuario = CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END
    FROM dbo.usuarios_menus_asignaciones usuario_menu_asignacion
    JOIN dbo.menus menu ON usuario_menu_asignacion.id_menu = menu.id_menu
    -- si tiene estos 4 existe la asignacion del MENU AL ROL
    WHERE
    usuario_menu_asignacion.estado <> 3
    AND usuario_menu_asignacion.id_usuario = @id_usuario
    AND menu.codigo_menu = @varCodigoMenu
    AND menu.id_modulo = @varIdModulo
    ;

    -- Resultado final: si hay directo, usa directo; si no hay, usa rol
    -- “bit a bit” (si los valores son 0 o 1):
    DECLARE @tiene_menu INT = @menu_usuario | @menu_rol;

    -- Aquí puedes devolverlos o usarlos como necesites
    SELECT 
        @tiene_menu AS acceso
        ;
END;
GO

-- EXEC obtain_usuario_has_menu
--     @varUsuario = 'SERGICAST02'
--     ,@varIdModulo = 3
--     ,@varCodigoMenu = 'screen_tarjetas'
--     ;


DROP PROCEDURE IF EXISTS dbo.obtain_menus_usuario;
GO
CREATE PROCEDURE dbo.obtain_menus_usuario
    @varUsuario VARCHAR(50),
    @varIdModulo INT
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @id_usuario INT;
    DECLARE @id_rol INT;

    -- Obtener ID del usuario
    SELECT @id_usuario = id_usuario
    FROM dbo.usuarios
    WHERE usuario = @varUsuario;

    IF @id_usuario IS NULL
    BEGIN
        RAISERROR('El usuario especificado no existe.', 16, 1);
        RETURN;
    END;

    -- Obtener el único rol del usuario asociado al módulo solicitado
    SELECT TOP 1
        @id_rol = URA.id_rol
    FROM dbo.usuarios_roles_asignados URA
    JOIN dbo.usuarios_roles_tipos URT ON URA.id_rol = URT.id_rol
    WHERE URA.id_usuario = @id_usuario
      AND URT.id_modulo = @varIdModulo;

    -- Menús asignados directamente al usuario
    WITH MenusUsuario AS (
        SELECT 
            M.id_menu,
            M.codigo_menu,
            M.menu,
            M.id_modulo
        FROM dbo.usuarios_menus_asignaciones UMA
        JOIN dbo.menus M ON UMA.id_menu = M.id_menu
        WHERE UMA.estado <> 3
          AND UMA.id_usuario = @id_usuario
          AND M.id_modulo = @varIdModulo
    ),

    -- Menús asignados al rol del usuario (solo el rol correspondiente al módulo)
    MenusRol AS (
        SELECT 
            M.id_menu,
            M.codigo_menu,
            M.menu,
            M.id_modulo
        FROM dbo.menus_roles MR
        JOIN dbo.menus M ON MR.id_menu = M.id_menu
        WHERE MR.id_rol = @id_rol
          AND M.id_modulo = @varIdModulo
    )

    -- Unir ambos orígenes, eliminando duplicados
    SELECT DISTINCT 
        id_menu,
        codigo_menu,
        menu,
        id_modulo
    FROM (
        SELECT * FROM MenusUsuario
        UNION
        SELECT * FROM MenusRol
    ) AS MenusTotales
    ORDER BY codigo_menu;

END;
GO


-- EXEC obtain_menus_usuario
--     @varUsuario = 'SERGICAST02',
--     @varIdModulo = 3
--     ;