Funciones de Acceso Seguro para Reportes SQL
🔒

Funciones de Acceso Seguro para Reportes SQL

Nos complace anunciar la implementación de Funciones de Seguridad Integradas en nuestro motor de reportes. Estas funciones, desarrolladas en Ruby, actúan como "atajos" inteligentes que inyectan subconsultas (subqueries) predefinidas directamente en tu código SQL.

¿Por qué usar estas funciones?

El objetivo principal es simplificar la creación de reportes garantizando la seguridad de la información. Al utilizar estas funciones, el sistema aplica automáticamente la lógica de accessible_by_current_user, asegurando que cada usuario solo visualice los registros de nómina o contratos que tiene permitidos según su segmento, sin que el desarrollador tenga que escribir complejas reglas de filtrado manualmente.

🛠 Detalle de las Funciones Disponibles

1. @func_access_payrolls_by_period()

Filtra los recibos de nómina (payrolls) basándose en IDs de periodos específicos.

  • Sin argumentos: Retorna todos los payrolls de todos los periodos a los que el usuario tiene acceso.
  • Con argumentos (1 a N): Retorna solo los payrolls de los IDs de periodos seleccionados.

Ejemplo de uso:

SQL

SELECT * FROM payrolls pa 
WHERE pa.id IN (@func_access_payrolls_by_period(:Previous_Period, :Current_Period))

2. @func_access_payrolls_by_period_date()

Filtra payrolls basándose en un rango de fechas de los periodos. Requiere obligatoriamente 3 argumentos: el campo de fecha a evaluar, la fecha inicial y la fecha final.

Ejemplo de uso:

SQL

SELECT * FROM payrolls pa 
WHERE pa.id IN (@func_access_payrolls_by_period_date(started_at, :from_st, :to_st))

3. @func_access_contracts_active()

Esta función no recibe argumentos. Devuelve los IDs de los contratos activos que el usuario actual tiene permiso de visualizar.

Ejemplo de uso:

SQL

SELECT * FROM payrolls pa 
WHERE pa.selected_contract_id IN (@func_access_contracts_active())

4. @func_access_contracts_by_date()

Similar a la anterior, pero permite filtrar contratos dentro de un rango de tiempo específico. Requiere el campo de fecha, fecha de inicio y fecha de fin.

Ejemplo de uso:

SQL

SELECT * FROM payrolls pa 
WHERE pa.selected_contract_id IN (@func_access_contracts_by_date(started_at, :from_st, :to_st))

5. Nueva Función Estructural: @func_concat()

Esta función es una herramienta técnica diseñada para concatenar múltiples valores separados por guiones bajos (_).

Finalidad: Generar identificadores únicos o nombres de columnas dinámicos, especialmente útil en reportes de tipo crosstab donde se necesita combinar tipos de periodo, parámetros y códigos de concepto de forma consistente.

  • Argumentos: Recibe una cadena de valores separados por comas.
  • Retorno: Una cadena única interpolada sin comillas.

Ejemplo de uso en SQL: Para generar un nombre de columna dinámico que combine el texto "periodo_base", el parámetro del periodo y el código del concepto:

SQL

-- Uso en la query:
@func_concat(periodo_base, :period_base, :code_concept)

-- Resultado generado:
"periodo_base_:period_base_:code_concept"

❓ Preguntas Frecuentes (FAQ)

Sobre @func_access_payrolls_by_period

  1. ¿Qué sucede si dejo los paréntesis vacíos? El sistema no filtrará por un periodo específico, sino que traerá todos los registros de nómina que el usuario tenga autorizados ver en toda la historia.
  2. ¿Puedo pasarle variables dinámicas como argumentos? Sí, la función acepta parámetros como :Current_period que son capturados desde los filtros del reporte.
  3. ¿Esta función mejora el rendimiento? Sí, al ser una subquery predefinida y optimizada por el sistema, es más eficiente que intentar hacer múltiples JOINs manuales para validar permisos.

Sobre @func_access_payrolls_by_period_date

  1. ¿Es obligatorio usar siempre los 3 argumentos? Sí. Para que la función procese el rango correctamente, necesita identificar el campo de la tabla y los dos límites de tiempo (:from_st y :to_st).
  2. ¿El campo de fecha debe ser obligatoriamente started_at? No necesariamente, puedes usar cualquier campo de tipo fecha de la tabla de payrolls que desees comparar contra el rango.
  3. ¿Qué pasa si el rango de fechas es nulo? La función retornará una consulta vacía o un error de ejecución, por lo que se recomienda asegurar que las variables de fecha tengan valores asignados.

Sobre @func_access_contracts_active

  1. ¿Qué define que un contrato sea "activo"? La función utiliza la lógica interna del negocio (generalmente contratos sin fecha de término o con fecha de término futura) y que pertenezcan al segmento del usuario.
  2. ¿Puedo usar esta función en un JOIN en lugar de un IN? Aunque está diseñada para usarse con IN(), técnicamente devuelve una subquery, pero la sintaxis recomendada para mantener la legibilidad es la del ejemplo.
  3. ¿Incluye contratos liquidados recientemente? No, esta función específica está optimizada para filtrar únicamente la vigencia actual.

Sobre @func_access_contracts_by_date

  1. ¿Cuál es la diferencia con la función de contratos activos? La de "activos" es una foto del presente; esta función te permite auditar o reportar sobre contratos que estuvieron vigentes en cualquier punto del tiempo que tú definas.
  2. ¿Puedo usarla para ver contratos futuros? Sí, siempre y cuando el rango de fechas que envíes en los argumentos coincida con la fecha de inicio de esos contratos.
  3. ¿Cómo se comporta si un contrato tiene acceso restringido por segmento? Prevalece la seguridad: aunque el contrato esté en el rango de fechas, si el usuario no tiene permiso para ver ese segmento, el ID no aparecerá en el resultado.

Sobre la nueva función @func_concat

  1. ¿Para qué sirve principalmente esta función? Se utiliza para crear nombres de columnas dinámicos en consultas complejas. Permite que el reporte genere encabezados o identificadores automáticos basados en los parámetros que el usuario elija.
  2. ¿Qué separador utiliza la función? Utiliza siempre el guion bajo (_). Esto asegura que los identificadores generados sean compatibles con los estándares de nombres de columnas en SQL.
  3. ¿Puedo usarla para concatenar campos de una tabla? No, su uso principal es la interpolación de texto y parámetros para construir la estructura de la query antes de que esta se ejecute (metaprogramación de SQL).