Files
Plataforma-de-desarrolladores/Procedimientos_Bitacora_Eventos_20260920.sql
Jorge Luis caudillo esparza e8160eefba --documentos
2026-09-27 14:44:12 -07:00

3758 lines
145 KiB
Transact-SQL
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Procedimientos para el modelo evento -> registros -> campos/relaciones.
Base, plantillas y detalle plano instalados el 20/09/2026 con autorización del usuario.
Requiere la migración de eventos y la columna Plantilla de
Ajuste_Bitacora_Plantillas_20260920.sql, en una transacción externa.
Para actualizar la base actual, ejecutar únicamente ese ajuste, que incluye los dos PA cambiados.
Add conserva su resultado CveBitacora; EventoRegistrar devuelve CveBitacoraEvento.
Los cuatro lectores anteriores conservan filtros, seguridad y forma de resultados.
*/
IF @@TRANCOUNT = 0 OR COL_LENGTH('dbo.Bit_Campos', 'Plantilla') IS NULL
OR COL_LENGTH('dbo.Bit_Bitacora', 'LlaveRegistroTexto') IS NULL
OR COL_LENGTH('dbo.Bit_Bitacora', 'DescripcionMovimiento') IS NOT NULL
THROW 51000, 'Instale la migración de eventos en la transacción del instalador.', 1;
GO
CREATE OR ALTER PROCEDURE dbo.PA_Bit_BitacoraAdd
@NombreTablaSQL varchar(128),
@CveTipoMovimiento tinyint,
@CveDefinicionAccion int = NULL,
@CveUsuarioAutoriza int = NULL,
@FechaAutorizacion datetime = NULL,
@LlaveRegistro nvarchar(250),
@DescripcionMovimiento nvarchar(1000),
@RelacionesXml xml,
@CamposXml xml = NULL,
@DiscriminarCamposSinCambios bit = 1,
@DireccionIP varchar(50) = NULL,
@NombreEquipo varchar(150) = NULL,
@Modulo varchar(150) = NULL,
@CveBitacoraEvento bigint = NULL,
@LlaveRegistroNumero bigint = NULL,
@EsLlaveTexto bit = 0,
@DevolverClave bit = 1,
@RegistrarSinCampos bit = 0,
@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT
@ErrorMostrar = NULL,
@ErrorTipo = 0,
@Return = 0;
BEGIN TRY
IF @@TRANCOUNT = 0
BEGIN
SET @ErrorMostrar = 'El registro de bitácora requiere la transacción del servicio.';
SET @ErrorTipo = 1;
RETURN;
END;
DECLARE @EsCompatibilidad bit = CASE WHEN @CveBitacoraEvento IS NULL THEN 1 ELSE 0 END;
DECLARE @CveTabla int;
SELECT @CveTabla = T.CveTabla
FROM dbo.Bit_Tablas AS T
WHERE T.NombreTablaSQL = @NombreTablaSQL
AND T.Activo = 1;
IF @CveTabla IS NULL
BEGIN
INSERT INTO [dbo].[Bit_Tablas]([NombreTablaSQL], [NombreMostrar], [Descripcion], [NombreCampoLlaveSQL], [Activo], [FechaAlta])
VALUES (@NombreTablaSQL, REPLACE(@NombreTablaSQL, '_', ' '), REPLACE(@NombreTablaSQL, '_', ' '), NULL, 1, GETDATE());
SELECT @CveTabla = T.CveTabla
FROM dbo.Bit_Tablas AS T
WHERE T.NombreTablaSQL = @NombreTablaSQL
AND T.Activo = 1;
END;
IF @CveTabla IS NULL
BEGIN
SET @ErrorMostrar = 'La tabla indicada no está configurada para bitácora.'+@NombreTablaSQL;
SET @ErrorTipo = 2;
RETURN;
END;
IF NOT EXISTS
(
SELECT 1
FROM dbo.Bit_TiposMovimiento AS M
WHERE M.CveTipoMovimiento = @CveTipoMovimiento
)
BEGIN
SET @ErrorMostrar = 'El tipo de movimiento de bitácora no es válido.';
SET @ErrorTipo = 2;
RETURN;
END;
IF @CveDefinicionAccion IS NOT NULL
AND NOT EXISTS
(
SELECT 1
FROM dbo.Bit_DefinicionesAccion AS A
WHERE A.CveDefinicionAccion = @CveDefinicionAccion
AND A.Activo = 1
)
BEGIN
SET @ErrorMostrar = 'La definición de la acción no corresponde al movimiento.';
SET @ErrorTipo = 2;
RETURN;
END;
DECLARE @Relaciones TABLE
(
Orden int NOT NULL,
CveTipoRelacion tinyint NOT NULL,
NombreTablaSQL varchar(128) NOT NULL,
NombreCampoSQL varchar(128) NOT NULL,
Valor nvarchar(250) NOT NULL,
VisibleDesarrollador bit NOT NULL,
DescripcionRelacion nvarchar(500) NULL
);
INSERT INTO @Relaciones
(
Orden,
CveTipoRelacion,
NombreTablaSQL,
NombreCampoSQL,
Valor,
VisibleDesarrollador,
DescripcionRelacion
)
SELECT
R.value('@Orden', 'int'),
R.value('@CveTipoRelacion', 'tinyint'),
R.value('@NombreTablaSQL', 'varchar(128)'),
R.value('@NombreCampoSQL', 'varchar(128)'),
R.value('@Valor', 'nvarchar(250)'),
R.value('@VisibleDesarrollador', 'bit'),
NULLIF(R.value('@DescripcionRelacion', 'nvarchar(500)'), '')
FROM @RelacionesXml.nodes('/Relaciones/Relacion') AS X(R);
IF NOT EXISTS (SELECT 1 FROM @Relaciones)
BEGIN
SET @ErrorMostrar = 'La bitácora debe incluir al menos una relación.';
SET @ErrorTipo = 2;
RETURN;
END;
/*==============================================================
AUTOCONFIGURAR TABLAS UTILIZADAS EN RELACIONES
==============================================================*/
INSERT INTO dbo.Bit_Tablas
(
NombreTablaSQL,
NombreMostrar,
Descripcion,
NombreCampoLlaveSQL,
Activo,
FechaAlta
)
SELECT DISTINCT
R.NombreTablaSQL,
REPLACE(R.NombreTablaSQL, '_', ' '),
REPLACE(R.NombreTablaSQL, '_', ' '),
NULL,
1,
GETDATE()
FROM @Relaciones AS R
INNER JOIN sys.schemas AS S ON S.name = 'dbo'
INNER JOIN sys.tables AS ST ON ST.schema_id = S.schema_id
AND ST.name = R.NombreTablaSQL
WHERE NOT EXISTS
(
SELECT 1
FROM dbo.Bit_Tablas AS T
WHERE T.NombreTablaSQL = R.NombreTablaSQL
);
/*==============================================================
AUTOCONFIGURAR CAMPOS UTILIZADOS EN RELACIONES
==============================================================*/
INSERT INTO dbo.Bit_Campos
(
CveTabla,
NombreCampoSQL,
NombreMostrar,
TipoDatoSQL,
MostrarEnBitacora,
Activo,
FechaAlta
)
SELECT DISTINCT
T.CveTabla,
R.NombreCampoSQL,
LTRIM
(
REPLACE
(
CASE
WHEN LEFT(R.NombreCampoSQL, 3) = 'Cve'
THEN SUBSTRING(R.NombreCampoSQL, 4, 125)
ELSE R.NombreCampoSQL
END,
'_',
' '
)
) AS NombreMostrar,
TYPE_NAME(SC.system_type_id) AS TipoDatoSQL,
1,
1,
GETDATE()
FROM @Relaciones AS R
INNER JOIN dbo.Bit_Tablas AS T ON T.NombreTablaSQL = R.NombreTablaSQL
AND T.Activo = 1
INNER JOIN sys.schemas AS S ON S.name = 'dbo'
INNER JOIN sys.tables AS ST ON ST.schema_id = S.schema_id
AND ST.name = R.NombreTablaSQL
INNER JOIN sys.columns AS SC ON SC.object_id = ST.object_id
AND SC.name = R.NombreCampoSQL
WHERE NOT EXISTS
(
SELECT 1
FROM dbo.Bit_Campos AS BC
WHERE BC.CveTabla = T.CveTabla
AND BC.NombreCampoSQL = R.NombreCampoSQL
);
DECLARE @RelacionesResueltas TABLE
(
Orden int NOT NULL,
CveTipoRelacion tinyint NOT NULL,
CveTabla int NOT NULL,
CveCampo int NOT NULL,
NombreTablaSQL varchar(128) NOT NULL,
NombreCampoSQL varchar(128) NOT NULL,
TipoDatoSQL varchar(128) NOT NULL,
Valor nvarchar(250) NOT NULL,
VisibleDesarrollador bit NOT NULL,
DescripcionRelacion nvarchar(500) NULL
);
INSERT INTO @RelacionesResueltas
(
Orden,
CveTipoRelacion,
CveTabla,
CveCampo,
NombreTablaSQL,
NombreCampoSQL,
TipoDatoSQL,
Valor,
VisibleDesarrollador,
DescripcionRelacion
)
SELECT
R.Orden,
R.CveTipoRelacion,
T.CveTabla,
C.CveCampo,
R.NombreTablaSQL,
R.NombreCampoSQL,
C.TipoDatoSQL,
R.Valor,
R.VisibleDesarrollador,
R.DescripcionRelacion
FROM @Relaciones AS R
INNER JOIN dbo.Bit_Tablas AS T ON T.NombreTablaSQL = R.NombreTablaSQL
AND T.Activo = 1
INNER JOIN dbo.Bit_Campos AS C ON C.CveTabla = T.CveTabla
AND C.NombreCampoSQL = R.NombreCampoSQL
AND C.Activo = 1
INNER JOIN dbo.Bit_TiposRelacion AS TR ON TR.CveTipoRelacion = R.CveTipoRelacion
AND TR.Activo = 1
WHERE C.TipoDatoSQL IS NOT NULL;
IF (SELECT COUNT(1) FROM @Relaciones) <>
(SELECT COUNT(1) FROM @RelacionesResueltas)
BEGIN
SET @ErrorMostrar = 'Una relación utiliza una tabla, campo o tipo que no está configurado en la bitácora.';
SET @ErrorTipo = 2;
RETURN;
END;
IF EXISTS
(
SELECT 1
FROM @RelacionesResueltas
WHERE TipoDatoSQL IN ('tinyint', 'smallint', 'int', 'bigint')
AND TRY_CONVERT(bigint, Valor) IS NULL
)
BEGIN
SET @ErrorMostrar = 'El valor de una relación numérica no es válido.';
SET @ErrorTipo = 2;
RETURN;
END;
IF EXISTS
(
SELECT 1
FROM @RelacionesResueltas
WHERE VisibleDesarrollador = 1
)
AND NOT EXISTS
(
SELECT 1
FROM @RelacionesResueltas
WHERE NombreTablaSQL = 'Clientes'
AND NombreCampoSQL = 'CveCliente'
AND VisibleDesarrollador = 1
)
BEGIN
SET @ErrorMostrar = 'Una bitácora visible para desarrolladores debe relacionarse con un cliente.';
SET @ErrorTipo = 2;
RETURN;
END;
DECLARE @Campos TABLE
(
Orden int NOT NULL,
NombreCampoSQL varchar(128) NOT NULL,
ValorAnteriorEsNulo bit NOT NULL,
ValorAnterior nvarchar(max) NULL,
ValorNuevoEsNulo bit NOT NULL,
ValorNuevo nvarchar(max) NULL,
ValorAnteriorMostrar nvarchar(max) NULL,
ValorNuevoMostrar nvarchar(max) NULL
);
IF @CamposXml IS NOT NULL
BEGIN
INSERT INTO @Campos
(
Orden,
NombreCampoSQL,
ValorAnteriorEsNulo,
ValorAnterior,
ValorNuevoEsNulo,
ValorNuevo,
ValorAnteriorMostrar,
ValorNuevoMostrar
)
SELECT
C.value('@Orden', 'int'),
C.value('@NombreCampoSQL', 'varchar(128)'),
C.value('@ValorAnteriorEsNulo', 'bit'),
CASE
WHEN C.value('@ValorAnteriorEsNulo', 'bit') = 1 THEN NULL
ELSE C.value('@ValorAnterior', 'nvarchar(max)')
END,
C.value('@ValorNuevoEsNulo', 'bit'),
CASE
WHEN C.value('@ValorNuevoEsNulo', 'bit') = 1 THEN NULL
ELSE C.value('@ValorNuevo', 'nvarchar(max)')
END,
CASE WHEN C.exist('@ValorAnteriorMostrar') = 1
THEN C.value('@ValorAnteriorMostrar', 'nvarchar(max)') END,
CASE WHEN C.exist('@ValorNuevoMostrar') = 1
THEN C.value('@ValorNuevoMostrar', 'nvarchar(max)') END
FROM @CamposXml.nodes('/Campos/Campo') AS X(C);
END;
IF @CveTipoMovimiento IN (1, 2)
AND NOT EXISTS (SELECT 1 FROM @Campos)
AND @RegistrarSinCampos = 0
BEGIN
SET @ErrorMostrar = 'Las altas y modificaciones deben incluir los campos auditados.';
SET @ErrorTipo = 2;
RETURN;
END;
/*==============================================================
AUTOCONFIGURAR CAMPOS AUDITADOS DE LA TABLA PRINCIPAL
==============================================================*/
INSERT INTO dbo.Bit_Campos
(
CveTabla,
NombreCampoSQL,
NombreMostrar,
TipoDatoSQL,
MostrarEnBitacora,
Activo,
FechaAlta
)
SELECT DISTINCT
@CveTabla,
F.NombreCampoSQL,
LTRIM
(
REPLACE
(
CASE
WHEN LEFT(F.NombreCampoSQL, 3) = 'Cve'
THEN SUBSTRING(F.NombreCampoSQL, 4, 125)
ELSE F.NombreCampoSQL
END,
'_',
' '
)
) AS NombreMostrar,
TYPE_NAME(SC.system_type_id) AS TipoDatoSQL,
1,
1,
GETDATE()
FROM @Campos AS F
INNER JOIN sys.schemas AS S ON S.name = 'dbo'
INNER JOIN sys.tables AS ST ON ST.schema_id = S.schema_id
AND ST.name = @NombreTablaSQL
INNER JOIN sys.columns AS SC ON SC.object_id = ST.object_id
AND SC.name = F.NombreCampoSQL
WHERE NOT EXISTS
(
SELECT 1
FROM dbo.Bit_Campos AS BC
WHERE BC.CveTabla = @CveTabla
AND BC.NombreCampoSQL = F.NombreCampoSQL
);
IF EXISTS
(
SELECT 1
FROM @Campos AS F
LEFT JOIN dbo.Bit_Campos AS C ON C.CveTabla = @CveTabla
AND C.NombreCampoSQL = F.NombreCampoSQL
AND C.Activo = 1
WHERE C.CveCampo IS NULL
)
BEGIN
SET @ErrorMostrar = 'Uno de los campos enviados no está configurado para la tabla auditada.';
SET @ErrorTipo = 2;
RETURN;
END;
DECLARE @ValoresPlantilla TABLE
(
CveBitacora bigint NOT NULL,
CveCampo int NOT NULL,
NombreCampoSQL varchar(128) COLLATE Modern_Spanish_CS_AS NOT NULL,
AliasReferencia varchar(128) COLLATE Modern_Spanish_CS_AS NULL,
TipoDatoSQL varchar(128) NULL,
MostrarEnBitacora bit NOT NULL,
ValorAnterior nvarchar(max) COLLATE Modern_Spanish_CS_AS NULL,
ValorNuevo nvarchar(max) COLLATE Modern_Spanish_CS_AS NULL,
ValorAnteriorMostrar nvarchar(max) COLLATE Modern_Spanish_CS_AS NULL,
ValorNuevoMostrar nvarchar(max) COLLATE Modern_Spanish_CS_AS NULL,
Orden int NOT NULL
);
DECLARE @RegistrosPlantilla TABLE
(
CveBitacora bigint NOT NULL PRIMARY KEY,
CveTabla int NOT NULL,
CveTipoMovimiento tinyint NOT NULL
);
DECLARE @ResultadosPlantilla TABLE
(
CveBitacora bigint NOT NULL,
CveCampo int NOT NULL,
ValorAnterior nvarchar(max) COLLATE Modern_Spanish_CS_AS NULL,
ValorNuevo nvarchar(max) COLLATE Modern_Spanish_CS_AS NULL,
Orden int NOT NULL
);
DECLARE @CamposSustituidos TABLE
(
CveBitacora bigint NOT NULL,
CveCampo int NOT NULL,
PRIMARY KEY (CveBitacora, CveCampo)
);
DECLARE @EsLecturaHistorica bit = 0;
INSERT INTO @RegistrosPlantilla(CveBitacora, CveTabla, CveTipoMovimiento)
VALUES (0, @CveTabla, @CveTipoMovimiento);
INSERT INTO @ValoresPlantilla
(
CveBitacora, CveCampo, NombreCampoSQL, AliasReferencia,
TipoDatoSQL, MostrarEnBitacora, ValorAnterior, ValorNuevo,
ValorAnteriorMostrar, ValorNuevoMostrar, Orden
)
SELECT
0, C.CveCampo, C.NombreCampoSQL, M.NombreCampoSQL,
C.TipoDatoSQL, C.MostrarEnBitacora, F.ValorAnterior, F.ValorNuevo,
F.ValorAnteriorMostrar, F.ValorNuevoMostrar, F.Orden
FROM @Campos AS F
INNER JOIN dbo.Bit_Campos AS C ON C.CveTabla = @CveTabla
AND C.NombreCampoSQL = F.NombreCampoSQL AND C.Activo = 1
LEFT JOIN dbo.Bit_Campos AS M ON M.CveCampo = C.CveCampoMostrarReferencia
AND M.CveTabla = C.CveTablaReferencia
WHERE C.Plantilla IS NULL;
-- Resolver referencias faltantes al registrar, conservando las imágenes enviadas.
DECLARE @CampoReferencia int;
DECLARE @TablaReferencia sysname;
DECLARE @LlaveReferencia sysname;
DECLARE @MostrarReferencia sysname;
DECLARE @AnteriorReferencia nvarchar(max);
DECLARE @NuevoReferencia nvarchar(max);
DECLARE @AnteriorResuelto nvarchar(max);
DECLARE @NuevoResuelto nvarchar(max);
DECLARE @ConsultaReferencia nvarchar(max);
DECLARE CursorReferenciasRegistro CURSOR LOCAL FAST_FORWARD FOR
SELECT V.CveCampo, T.NombreTablaSQL, T.NombreCampoLlaveSQL,
M.NombreCampoSQL, V.ValorAnterior, V.ValorNuevo
FROM @ValoresPlantilla AS V
INNER JOIN dbo.Bit_Campos AS C ON C.CveCampo = V.CveCampo
INNER JOIN dbo.Bit_Tablas AS T ON T.CveTabla = C.CveTablaReferencia AND T.Activo = 1
INNER JOIN dbo.Bit_Campos AS M ON M.CveCampo = C.CveCampoMostrarReferencia
AND M.CveTabla = T.CveTabla AND M.Activo = 1 AND M.MostrarEnBitacora = 1
INNER JOIN sys.tables AS ST ON ST.name COLLATE Modern_Spanish_CS_AS = T.NombreTablaSQL
AND ST.schema_id = SCHEMA_ID('dbo')
INNER JOIN sys.columns AS CL ON CL.object_id = ST.object_id
AND CL.name COLLATE Modern_Spanish_CS_AS = T.NombreCampoLlaveSQL
INNER JOIN sys.columns AS CM ON CM.object_id = ST.object_id
AND CM.name COLLATE Modern_Spanish_CS_AS = M.NombreCampoSQL
WHERE (V.ValorAnterior IS NOT NULL AND V.ValorAnteriorMostrar IS NULL)
OR (V.ValorNuevo IS NOT NULL AND V.ValorNuevoMostrar IS NULL);
OPEN CursorReferenciasRegistro;
FETCH NEXT FROM CursorReferenciasRegistro INTO
@CampoReferencia, @TablaReferencia, @LlaveReferencia, @MostrarReferencia,
@AnteriorReferencia, @NuevoReferencia;
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @AnteriorResuelto = NULL, @NuevoResuelto = NULL;
SET @ConsultaReferencia = N'
SELECT @AnteriorMostrar = CONVERT(nvarchar(max), ' + QUOTENAME(@MostrarReferencia) + N')
FROM dbo.' + QUOTENAME(@TablaReferencia) + N'
WHERE CONVERT(nvarchar(250), ' + QUOTENAME(@LlaveReferencia) + N') = @Anterior;
SELECT @NuevoMostrar = CONVERT(nvarchar(max), ' + QUOTENAME(@MostrarReferencia) + N')
FROM dbo.' + QUOTENAME(@TablaReferencia) + N'
WHERE CONVERT(nvarchar(250), ' + QUOTENAME(@LlaveReferencia) + N') = @Nuevo;';
EXEC sys.sp_executesql @ConsultaReferencia,
N'@Anterior nvarchar(max), @Nuevo nvarchar(max),
@AnteriorMostrar nvarchar(max) OUTPUT, @NuevoMostrar nvarchar(max) OUTPUT',
@Anterior = @AnteriorReferencia, @Nuevo = @NuevoReferencia,
@AnteriorMostrar = @AnteriorResuelto OUTPUT,
@NuevoMostrar = @NuevoResuelto OUTPUT;
UPDATE @ValoresPlantilla
SET ValorAnteriorMostrar = COALESCE(ValorAnteriorMostrar, @AnteriorResuelto),
ValorNuevoMostrar = COALESCE(ValorNuevoMostrar, @NuevoResuelto)
WHERE CveCampo = @CampoReferencia;
FETCH NEXT FROM CursorReferenciasRegistro INTO
@CampoReferencia, @TablaReferencia, @LlaveReferencia, @MostrarReferencia,
@AnteriorReferencia, @NuevoReferencia;
END;
CLOSE CursorReferenciasRegistro;
DEALLOCATE CursorReferenciasRegistro;
UPDATE @ValoresPlantilla
SET
ValorAnteriorMostrar = COALESCE(ValorAnteriorMostrar,
CASE
WHEN ValorAnterior IS NULL THEN NULL
WHEN TipoDatoSQL = 'bit' AND ValorAnterior IN (N'0', N'1')
THEN CASE WHEN ValorAnterior = N'1' THEN N'Sí' ELSE N'No' END
WHEN TipoDatoSQL = 'time' AND TRY_CONVERT(time, ValorAnterior) IS NOT NULL
THEN LEFT(CONVERT(varchar(16), TRY_CONVERT(time, ValorAnterior), 108), 5)
END),
ValorNuevoMostrar = COALESCE(ValorNuevoMostrar,
CASE
WHEN ValorNuevo IS NULL THEN NULL
WHEN TipoDatoSQL = 'bit' AND ValorNuevo IN (N'0', N'1')
THEN CASE WHEN ValorNuevo = N'1' THEN N'Sí' ELSE N'No' END
WHEN TipoDatoSQL = 'time' AND TRY_CONVERT(time, ValorNuevo) IS NOT NULL
THEN LEFT(CONVERT(varchar(16), TRY_CONVERT(time, ValorNuevo), 108), 5)
END);
-- Sustitución literal de tokens; nunca se ejecuta el contenido de una plantilla.
DECLARE @RegistroPlantilla bigint;
DECLARE @TablaPlantilla int;
DECLARE @CampoPlantilla int;
DECLARE @TextoPlantilla nvarchar(1000);
DECLARE @MovimientoPlantilla tinyint;
DECLARE @Pendiente nvarchar(max);
DECLARE @AnteriorPlantilla nvarchar(max);
DECLARE @NuevoPlantilla nvarchar(max);
DECLARE @InicioToken int;
DECLARE @FinToken int;
DECLARE @Token nvarchar(128);
DECLARE @CampoToken int;
DECLARE @Coincidencias int;
DECLARE @AnteriorToken nvarchar(max);
DECLARE @NuevoToken nvarchar(max);
DECLARE @Completa bit;
DECLARE @CamposUsados TABLE (CveCampo int NOT NULL PRIMARY KEY);
DECLARE CursorPlantillas CURSOR LOCAL FAST_FORWARD FOR
SELECT R.CveBitacora, R.CveTabla, P.CveCampo, P.Plantilla, R.CveTipoMovimiento
FROM @RegistrosPlantilla AS R
INNER JOIN dbo.Bit_Campos AS P ON P.CveTabla = R.CveTabla
WHERE P.Activo = 1
AND P.MostrarEnBitacora = 1
AND P.Plantilla IS NOT NULL
AND NOT EXISTS
(
SELECT 1
FROM @ValoresPlantilla AS V
WHERE V.CveBitacora = R.CveBitacora AND V.CveCampo = P.CveCampo
)
ORDER BY R.CveBitacora, P.CveCampo;
OPEN CursorPlantillas;
FETCH NEXT FROM CursorPlantillas INTO
@RegistroPlantilla, @TablaPlantilla, @CampoPlantilla,
@TextoPlantilla, @MovimientoPlantilla;
WHILE @@FETCH_STATUS = 0
BEGIN
DELETE FROM @CamposUsados;
SELECT
@Pendiente = @TextoPlantilla,
@AnteriorPlantilla = N'',
@NuevoPlantilla = N'',
@Completa = 1;
WHILE LEN(@Pendiente) > 0
BEGIN
SET @InicioToken = CHARINDEX(N'{', @Pendiente);
IF @InicioToken = 0
BEGIN
IF CHARINDEX(N'}', @Pendiente) > 0
SET @Completa = 0;
SET @AnteriorPlantilla += @Pendiente;
SET @NuevoPlantilla += @Pendiente;
BREAK;
END;
SET @FinToken = CHARINDEX(N'}', @Pendiente, @InicioToken + 1);
IF @FinToken = 0 OR @FinToken - @InicioToken NOT BETWEEN 2 AND 129
OR CHARINDEX(N'}', LEFT(@Pendiente, @InicioToken - 1)) > 0
BEGIN
SET @Completa = 0;
BREAK;
END;
SET @Token = SUBSTRING(@Pendiente, @InicioToken + 1, @FinToken - @InicioToken - 1);
SET @CampoToken = NULL;
SELECT @Coincidencias = COUNT(*), @CampoToken = MIN(CveCampo)
FROM @ValoresPlantilla
WHERE CveBitacora = @RegistroPlantilla
AND NombreCampoSQL = @Token;
IF @Coincidencias = 0
BEGIN
SELECT @Coincidencias = COUNT(*), @CampoToken = MIN(CveCampo)
FROM @ValoresPlantilla
WHERE CveBitacora = @RegistroPlantilla
AND AliasReferencia = @Token;
END;
IF @Coincidencias <> 1 OR EXISTS
(
SELECT 1 FROM dbo.Bit_Campos
WHERE CveCampo = @CampoToken AND Plantilla IS NOT NULL
)
BEGIN
SET @Completa = 0;
BREAK;
END;
-- Una clave de catálogo sin texto histórico no permite reconstruir su nombre anterior.
IF EXISTS
(
SELECT 1
FROM @ValoresPlantilla
WHERE CveBitacora = @RegistroPlantilla AND CveCampo = @CampoToken
AND AliasReferencia IS NOT NULL
AND
(
(ValorAnterior IS NOT NULL AND ValorAnteriorMostrar IS NULL)
OR (ValorNuevo IS NOT NULL AND ValorNuevoMostrar IS NULL)
)
)
BEGIN
SET @Completa = 0;
BREAK;
END;
SELECT
@AnteriorToken = COALESCE(ValorAnteriorMostrar, ValorAnterior, N''),
@NuevoToken = COALESCE(ValorNuevoMostrar, ValorNuevo, N'')
FROM @ValoresPlantilla
WHERE CveBitacora = @RegistroPlantilla AND CveCampo = @CampoToken;
SET @AnteriorPlantilla += LEFT(@Pendiente, @InicioToken - 1) + @AnteriorToken;
SET @NuevoPlantilla += LEFT(@Pendiente, @InicioToken - 1) + @NuevoToken;
SET @Pendiente = SUBSTRING(@Pendiente, @FinToken + 1, LEN(@Pendiente));
IF NOT EXISTS (SELECT 1 FROM @CamposUsados WHERE CveCampo = @CampoToken)
INSERT INTO @CamposUsados(CveCampo) VALUES (@CampoToken);
END;
IF NOT EXISTS (SELECT 1 FROM @CamposUsados)
SET @Completa = 0;
IF @Completa = 1
BEGIN
INSERT INTO @ResultadosPlantilla
(CveBitacora, CveCampo, ValorAnterior, ValorNuevo, Orden)
SELECT
@RegistroPlantilla,
@CampoPlantilla,
CASE WHEN @MovimientoPlantilla = 1 THEN NULL ELSE @AnteriorPlantilla END,
CASE WHEN @MovimientoPlantilla = 3 THEN NULL ELSE @NuevoPlantilla END,
MIN(V.Orden)
FROM @ValoresPlantilla AS V
INNER JOIN @CamposUsados AS U ON U.CveCampo = V.CveCampo
WHERE V.CveBitacora = @RegistroPlantilla;
INSERT INTO @CamposSustituidos(CveBitacora, CveCampo)
SELECT @RegistroPlantilla, U.CveCampo
FROM @CamposUsados AS U
INNER JOIN @ValoresPlantilla AS V ON V.CveBitacora = @RegistroPlantilla
AND V.CveCampo = U.CveCampo
WHERE V.MostrarEnBitacora = 0
AND NOT EXISTS
(
SELECT 1 FROM @CamposSustituidos AS S
WHERE S.CveBitacora = @RegistroPlantilla AND S.CveCampo = U.CveCampo
);
END
ELSE IF @EsLecturaHistorica = 0
BEGIN
CLOSE CursorPlantillas;
DEALLOCATE CursorPlantillas;
SET @ErrorMostrar = 'No se pudo formar la plantilla de bitácora: revise sus campos y valores mostrables.';
SET @ErrorTipo = 2;
RETURN;
END;
FETCH NEXT FROM CursorPlantillas INTO
@RegistroPlantilla, @TablaPlantilla, @CampoPlantilla,
@TextoPlantilla, @MovimientoPlantilla;
END;
CLOSE CursorPlantillas;
DEALLOCATE CursorPlantillas;
IF @CveBitacoraEvento IS NULL
BEGIN
INSERT INTO dbo.Bit_BitacoraEventos
(
CveDefinicionAccion, CveUsuarioEjecuta, CveUsuarioAutoriza,
FechaAutorizacion, DescripcionMovimiento, DireccionIP, NombreEquipo, Modulo
)
VALUES
(
@CveDefinicionAccion, @CveUsuarioEjecuta, @CveUsuarioAutoriza,
@FechaAutorizacion, @DescripcionMovimiento, @DireccionIP, @NombreEquipo, @Modulo
);
SET @CveBitacoraEvento = CONVERT(bigint, SCOPE_IDENTITY());
END;
INSERT INTO dbo.Bit_Bitacora
(
CveBitacoraEvento, CveTabla, CveTipoMovimiento, LlaveRegistro, LlaveRegistroTexto
)
VALUES
(
@CveBitacoraEvento, @CveTabla, @CveTipoMovimiento,
CASE WHEN @EsCompatibilidad = 1 THEN TRY_CONVERT(bigint, @LlaveRegistro)
WHEN @EsLlaveTexto = 0 THEN @LlaveRegistroNumero END,
CASE WHEN @EsCompatibilidad = 1 OR @EsLlaveTexto = 1 THEN @LlaveRegistro END
);
DECLARE @CveBitacora bigint = CONVERT(bigint, SCOPE_IDENTITY());
INSERT INTO dbo.Bit_BitacoraRelaciones
(
CveBitacora,
CveTipoRelacion,
CveTablaRelacionada,
LlaveRegistroRelacionada,
CveCampoRelacion,
ValorRelacionNumero,
ValorRelacionTexto,
DescripcionRelacion,
VisibleDesarrollador
)
SELECT
@CveBitacora,
R.CveTipoRelacion,
R.CveTabla,
R.Valor,
R.CveCampo,
CASE
WHEN R.TipoDatoSQL IN ('tinyint', 'smallint', 'int', 'bigint')
THEN TRY_CONVERT(bigint, R.Valor)
ELSE NULL
END,
CASE
WHEN R.TipoDatoSQL IN ('tinyint', 'smallint', 'int', 'bigint')
THEN NULL
ELSE R.Valor
END,
R.DescripcionRelacion,
R.VisibleDesarrollador
FROM @RelacionesResueltas AS R;
;WITH CamposGuardar AS
(
SELECT CveCampo, ValorAnterior, ValorNuevo,
ValorAnteriorMostrar, ValorNuevoMostrar
FROM @ValoresPlantilla
WHERE MostrarEnBitacora = 1
UNION ALL
SELECT CveCampo, ValorAnterior, ValorNuevo, ValorAnterior, ValorNuevo
FROM @ResultadosPlantilla
)
INSERT INTO dbo.Bit_BitacoraCampos
(
CveBitacora, CveCampo, ValorAnterior, ValorNuevo,
ValorAnteriorMostrar, ValorNuevoMostrar
)
SELECT
@CveBitacora, F.CveCampo, F.ValorAnterior, F.ValorNuevo,
F.ValorAnteriorMostrar, F.ValorNuevoMostrar
FROM CamposGuardar AS F
WHERE @DiscriminarCamposSinCambios = 0
OR (F.ValorAnterior IS NULL AND F.ValorNuevo IS NOT NULL)
OR (F.ValorAnterior IS NOT NULL AND F.ValorNuevo IS NULL)
OR DATALENGTH(F.ValorAnterior) <> DATALENGTH(F.ValorNuevo)
OR F.ValorAnterior COLLATE Latin1_General_100_BIN2 <>
F.ValorNuevo COLLATE Latin1_General_100_BIN2
OR (F.ValorAnteriorMostrar IS NULL AND F.ValorNuevoMostrar IS NOT NULL)
OR (F.ValorAnteriorMostrar IS NOT NULL AND F.ValorNuevoMostrar IS NULL)
OR DATALENGTH(F.ValorAnteriorMostrar) <> DATALENGTH(F.ValorNuevoMostrar)
OR F.ValorAnteriorMostrar COLLATE Latin1_General_100_BIN2 <>
F.ValorNuevoMostrar COLLATE Latin1_General_100_BIN2;
IF @DevolverClave = 1
SELECT @CveBitacora AS CveBitacora;
SET @Return = 1;
END TRY
BEGIN CATCH
SET @ErrorMostrar = 'Ocurrió un error al registrar la bitácora; favor de contactar a Sistemas.';
SET @ErrorTipo = 1;
SET @Return = 0;
DECLARE @ErrorTecnico nvarchar(2048) = CONCAT(
'Número: ', ERROR_NUMBER(),
'; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Bit_BitacoraAdd'),
'; Línea: ', ERROR_LINE(),
'; Detalle: ', ERROR_MESSAGE()
);
RAISERROR(N'%s', 10, 1, @ErrorTecnico);
END CATCH;
END;
GO
CREATE OR ALTER PROCEDURE dbo.PA_Bit_BitacoraEventoRegistrar
@CodigoAccion varchar(150),
@DescripcionMovimiento nvarchar(1000),
@CveUsuarioAutoriza int = NULL,
@FechaAutorizacion datetime2(3) = NULL,
@DireccionIP varchar(50) = NULL,
@NombreEquipo varchar(150) = NULL,
@Modulo varchar(150) = NULL,
@RegistrosXml xml,
@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0;
BEGIN TRY
IF @@TRANCOUNT = 0
BEGIN
SET @ErrorMostrar = 'La operación requiere una transacción del servicio.';
SET @ErrorTipo = 1;
RETURN;
END;
DECLARE @CveDefinicionAccion int;
SELECT @CveDefinicionAccion = CveDefinicionAccion
FROM dbo.Bit_DefinicionesAccion
WHERE CodigoAccion = @CodigoAccion AND Activo = 1;
IF @CveDefinicionAccion IS NULL OR @RegistrosXml IS NULL
OR @RegistrosXml.exist('/Registros/Registro') = 0
BEGIN
SET @ErrorMostrar = 'La acción no está configurada o no contiene registros.';
SET @ErrorTipo = 2;
RETURN;
END;
DECLARE @Registros TABLE
(
Orden int NOT NULL PRIMARY KEY,
Datos xml NOT NULL
);
INSERT INTO @Registros(Orden, Datos)
SELECT R.value('@Orden', 'int'), R.query('.')
FROM @RegistrosXml.nodes('/Registros/Registro') AS X(R);
INSERT INTO dbo.Bit_BitacoraEventos
(
CveDefinicionAccion, CveUsuarioEjecuta, CveUsuarioAutoriza,
FechaAutorizacion, DescripcionMovimiento, DireccionIP, NombreEquipo, Modulo
)
VALUES
(
@CveDefinicionAccion, @CveUsuarioEjecuta, @CveUsuarioAutoriza,
@FechaAutorizacion, @DescripcionMovimiento, @DireccionIP, @NombreEquipo, @Modulo
);
DECLARE @CveBitacoraEvento bigint = CONVERT(bigint, SCOPE_IDENTITY());
DECLARE @Orden int = 0;
DECLARE @Datos xml;
DECLARE @Tabla varchar(128);
DECLARE @Movimiento tinyint;
DECLARE @LlaveNumero bigint;
DECLARE @LlaveTexto nvarchar(250);
DECLARE @EsLlaveTexto bit;
DECLARE @Discriminar bit;
DECLARE @RegistrarSinCampos bit;
DECLARE @Campos xml;
DECLARE @Relaciones xml;
WHILE EXISTS (SELECT 1 FROM @Registros WHERE Orden > @Orden)
BEGIN
SELECT TOP (1) @Orden = Orden, @Datos = Datos
FROM @Registros
WHERE Orden > @Orden
ORDER BY Orden;
SELECT
@Tabla = @Datos.value('(/Registro/@NombreTablaSQL)[1]', 'varchar(128)'),
@Movimiento = @Datos.value('(/Registro/@CveTipoMovimiento)[1]', 'tinyint'),
@EsLlaveTexto = @Datos.exist('/Registro/@LlaveRegistroTexto'),
@LlaveNumero = CASE WHEN @Datos.exist('/Registro/@LlaveRegistro') = 1
THEN @Datos.value('(/Registro/@LlaveRegistro)[1]', 'bigint') END,
@LlaveTexto = CASE WHEN @Datos.exist('/Registro/@LlaveRegistroTexto') = 1
THEN @Datos.value('(/Registro/@LlaveRegistroTexto)[1]', 'nvarchar(250)') END,
@RegistrarSinCampos = CASE
WHEN @Datos.exist('/Registro/@RegistrarSinCampos') = 1
THEN @Datos.value('(/Registro/@RegistrarSinCampos)[1]', 'bit') ELSE 0 END,
@Discriminar = @Datos.value('(/Registro/@DiscriminarCamposSinCambios)[1]', 'bit'),
@Campos = @Datos.query('/Registro/Campos'),
@Relaciones = @Datos.query('/Registro/Relaciones');
IF (@EsLlaveTexto = 0 AND @LlaveNumero IS NULL)
OR (@EsLlaveTexto = 1 AND (@LlaveNumero IS NOT NULL OR NULLIF(@LlaveTexto, N'') IS NULL))
BEGIN
SET @ErrorMostrar = 'La clave del registro de bitácora no es válida.';
SET @ErrorTipo = 2;
SET @Return = 0;
RETURN;
END;
EXEC dbo.PA_Bit_BitacoraAdd
@NombreTablaSQL = @Tabla,
@CveTipoMovimiento = @Movimiento,
@CveDefinicionAccion = @CveDefinicionAccion,
@LlaveRegistro = @LlaveTexto,
@LlaveRegistroNumero = @LlaveNumero,
@EsLlaveTexto = @EsLlaveTexto,
@CveBitacoraEvento = @CveBitacoraEvento,
@DescripcionMovimiento = @DescripcionMovimiento,
@CamposXml = @Campos,
@RelacionesXml = @Relaciones,
@DiscriminarCamposSinCambios = @Discriminar,
@DevolverClave = 0,
@RegistrarSinCampos = @RegistrarSinCampos,
@CveUsuarioEjecuta = @CveUsuarioEjecuta,
@ErrorMostrar = @ErrorMostrar OUTPUT,
@ErrorTipo = @ErrorTipo OUTPUT,
@Return = @Return OUTPUT;
IF @Return = 0 RETURN;
END;
SELECT @CveBitacoraEvento AS CveBitacoraEvento;
SET @Return = 1;
END TRY
BEGIN CATCH
SET @ErrorMostrar = 'No fue posible completar la operación de bitácora. Contacte a Sistemas.';
SET @ErrorTipo = 1;
SET @Return = 0;
DECLARE @ErrorTecnico nvarchar(2048) = CONCAT(
'Número: ', ERROR_NUMBER(),
'; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Bit_BitacoraEventoRegistrar'),
'; Línea: ', ERROR_LINE(),
'; Detalle: ', ERROR_MESSAGE()
);
RAISERROR(N'%s', 10, 1, @ErrorTecnico);
END CATCH;
END;
GO
CREATE OR ALTER PROCEDURE dbo.PA_Bit_BitacoraEventoListar
@RelacionesXml xml = NULL,
@RelacionesMostrarXml xml = NULL,
@RegistrosOmitidos int,
@RegistrosPorPagina int,
@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0;
BEGIN TRY
IF @RegistrosOmitidos < 0 OR @RegistrosPorPagina NOT BETWEEN 1 AND 100
BEGIN
SET @ErrorMostrar = 'La paginación no es válida.';
SET @ErrorTipo = 2;
RETURN;
END;
DECLARE @EsAdministrador bit = 0;
DECLARE @EsDesarrollador bit = 0;
SELECT
@EsAdministrador = CASE
WHEN R.NombreRol IN ('SuperUsuario', 'Administrador') THEN 1
ELSE 0
END,
@EsDesarrollador = CASE
WHEN R.NombreRol = 'Empresa' THEN 1
ELSE 0
END
FROM dbo.Sis_Usuarios AS U
INNER JOIN dbo.Sis_Roles AS R ON R.CveRol = U.CveRol
WHERE U.CveUsuario = @CveUsuarioEjecuta
AND U.Activo = 1
AND R.Activo = 1;
DECLARE @Filtros TABLE
(
Orden int NOT NULL PRIMARY KEY,
NombreTablaSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreCampoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
Valor nvarchar(250)
COLLATE Modern_Spanish_CS_AS NOT NULL,
SoloExistencia bit NOT NULL
);
IF @RelacionesXml IS NOT NULL
BEGIN
INSERT INTO @Filtros(Orden, NombreTablaSQL, NombreCampoSQL, Valor, SoloExistencia)
SELECT R.value('@Orden', 'int'),
R.value('@Tabla', 'varchar(128)'),
R.value('@Campo', 'varchar(128)'),
R.value('@Valor', 'nvarchar(250)'),
COALESCE(R.value('@SoloExistencia', 'bit'), 0)
FROM @RelacionesXml.nodes('/Relaciones/Relacion') AS X(R);
END;
DECLARE @FiltrosResueltos TABLE
(
Orden int NOT NULL PRIMARY KEY,
CveTabla int NOT NULL,
CveCampo int NOT NULL,
TipoDatoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
Valor nvarchar(250)
COLLATE Modern_Spanish_CS_AS NOT NULL,
SoloExistencia bit NOT NULL,
EsEntero bit NOT NULL
);
INSERT INTO @FiltrosResueltos
(
Orden,
CveTabla,
CveCampo,
TipoDatoSQL,
Valor,
SoloExistencia,
EsEntero
)
SELECT
F.Orden,
T.CveTabla,
C.CveCampo,
C.TipoDatoSQL,
F.Valor,
F.SoloExistencia,
CASE
WHEN C.TipoDatoSQL IN
(
'tinyint',
'smallint',
'int',
'bigint'
) THEN 1
ELSE 0
END
FROM @Filtros AS F
INNER JOIN dbo.Bit_Tablas AS T ON T.NombreTablaSQL = F.NombreTablaSQL
AND T.Activo = 1
INNER JOIN dbo.Bit_Campos AS C ON C.CveTabla = T.CveTabla
AND C.NombreCampoSQL = F.NombreCampoSQL
AND C.Activo = 1
INNER JOIN sys.schemas AS SF ON SF.name = 'dbo'
INNER JOIN sys.tables AS TF ON TF.schema_id = SF.schema_id
AND TF.name COLLATE Modern_Spanish_CS_AS = T.NombreTablaSQL
INNER JOIN sys.columns AS CF ON CF.object_id = TF.object_id
AND CF.name COLLATE Modern_Spanish_CS_AS = C.NombreCampoSQL
WHERE C.TipoDatoSQL IS NOT NULL;
IF (SELECT COUNT(1) FROM @Filtros) <>
(SELECT COUNT(1) FROM @FiltrosResueltos)
BEGIN
SET @ErrorMostrar = 'Una relación utiliza una tabla o campo que no está configurado en la bitácora.';
SET @ErrorTipo = 2;
RETURN;
END;
IF EXISTS
(
SELECT 1
FROM @FiltrosResueltos
WHERE SoloExistencia = 0
AND EsEntero = 1
AND TRY_CONVERT(bigint, Valor) IS NULL
)
BEGIN
SET @ErrorMostrar = 'El valor de una relación numérica no es válido.';
SET @ErrorTipo = 2;
RETURN;
END;
CREATE TABLE #RegistrosAutorizados
(
CveBitacora bigint NOT NULL PRIMARY KEY
);
INSERT INTO #RegistrosAutorizados
SELECT B.CveBitacora
FROM dbo.Bit_Bitacora AS B
WHERE
(
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BRCliente
INNER JOIN dbo.Bit_Tablas AS TCliente ON TCliente.CveTabla =
BRCliente.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS CCliente ON CCliente.CveCampo =
BRCliente.CveCampoRelacion
AND CCliente.CveTabla = TCliente.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente =
BRCliente.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BRCliente.CveBitacora = B.CveBitacora
AND BRCliente.VisibleDesarrollador = 1
AND TCliente.NombreTablaSQL = 'Clientes'
AND CCliente.NombreCampoSQL = 'CveCliente'
)
)
);
CREATE TABLE #EventosCoincidentes
(
CveBitacoraEvento bigint NOT NULL PRIMARY KEY,
FechaMovimiento datetime2(3) NOT NULL
);
INSERT INTO #EventosCoincidentes
SELECT DISTINCT B.CveBitacoraEvento, E.FechaMovimiento
FROM dbo.Bit_Bitacora AS B
INNER JOIN #RegistrosAutorizados AS V ON V.CveBitacora = B.CveBitacora
INNER JOIN dbo.Bit_BitacoraEventos AS E ON E.CveBitacoraEvento = B.CveBitacoraEvento
WHERE 1 = 1
AND
(
@EsDesarrollador = 0
OR NOT EXISTS
(
SELECT 1
FROM @FiltrosResueltos AS FCliente
INNER JOIN dbo.Bit_Tablas AS TClienteFiltro ON TClienteFiltro.CveTabla = FCliente.CveTabla
INNER JOIN dbo.Bit_Campos AS CClienteFiltro ON CClienteFiltro.CveCampo = FCliente.CveCampo
AND CClienteFiltro.CveTabla =
TClienteFiltro.CveTabla
WHERE TClienteFiltro.NombreTablaSQL = 'Clientes'
AND CClienteFiltro.NombreCampoSQL = 'CveCliente'
AND FCliente.SoloExistencia = 0
AND NOT EXISTS
(
SELECT 1
FROM dbo.Sis_UsuariosClientes AS UCClienteFiltro
WHERE UCClienteFiltro.CveUsuario =
@CveUsuarioEjecuta
AND UCClienteFiltro.CveCliente =
TRY_CONVERT(bigint, FCliente.Valor)
AND UCClienteFiltro.Activo = 1
)
)
)
AND NOT EXISTS
(
SELECT 1
FROM @FiltrosResueltos AS F
WHERE NOT EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BR
WHERE BR.CveBitacora = B.CveBitacora
AND BR.CveTablaRelacionada = F.CveTabla
AND BR.CveCampoRelacion = F.CveCampo
AND
(
@EsAdministrador = 1
OR BR.VisibleDesarrollador = 1
)
AND
(
F.SoloExistencia = 1
OR
(
(
F.EsEntero = 1
AND BR.ValorRelacionNumero =
TRY_CONVERT(bigint, F.Valor)
)
OR
(
F.EsEntero = 0
AND BR.ValorRelacionTexto =
F.Valor COLLATE Modern_Spanish_CS_AS
)
)
)
)
);
SELECT COUNT(*) AS TotalRegistros FROM #EventosCoincidentes;
SELECT
E.CveBitacoraEvento,
E.CveDefinicionAccion,
A.CodigoAccion,
COALESCE(A.NombreAccion, N'Evento histórico') AS NombreAccion,
E.CveUsuarioEjecuta,
COALESCE(NULLIF(U.NombreUsuario, ''), CONCAT('(', E.CveUsuarioEjecuta, ') Eliminado')) AS NombreUsuarioEjecuta,
E.CveUsuarioAutoriza,
E.FechaAutorizacion,
CASE WHEN EXISTS
(
SELECT 1 FROM dbo.Bit_Bitacora AS R
WHERE R.CveBitacoraEvento = E.CveBitacoraEvento
AND NOT EXISTS (SELECT 1 FROM #RegistrosAutorizados AS V WHERE V.CveBitacora = R.CveBitacora)
) THEN N'Operación con registros de acceso restringido.'
ELSE E.DescripcionMovimiento END AS DescripcionMovimiento,
E.FechaMovimiento,
E.DireccionIP,
E.NombreEquipo,
E.Modulo,
E.EsHistorico
FROM dbo.Bit_BitacoraEventos AS E
LEFT JOIN dbo.Bit_DefinicionesAccion AS A ON A.CveDefinicionAccion = E.CveDefinicionAccion
LEFT JOIN dbo.Sis_Usuarios AS U ON U.CveUsuario = E.CveUsuarioEjecuta
INNER JOIN #EventosCoincidentes AS C ON C.CveBitacoraEvento = E.CveBitacoraEvento
ORDER BY C.FechaMovimiento DESC, C.CveBitacoraEvento DESC
OFFSET @RegistrosOmitidos ROWS FETCH NEXT @RegistrosPorPagina ROWS ONLY;
SET @Return = 1;
END TRY
BEGIN CATCH
SET @ErrorMostrar = 'No fue posible completar la operación de bitácora. Contacte a Sistemas.';
SET @ErrorTipo = 1;
SET @Return = 0;
DECLARE @ErrorTecnico nvarchar(2048) = CONCAT(
'Número: ', ERROR_NUMBER(),
'; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Bit_BitacoraEventoListar'),
'; Línea: ', ERROR_LINE(),
'; Detalle: ', ERROR_MESSAGE()
);
RAISERROR(N'%s', 10, 1, @ErrorTecnico);
END CATCH;
END;
GO
CREATE OR ALTER PROCEDURE dbo.PA_Bit_BitacoraEventoObtener
@CveBitacoraEvento bigint,
@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0;
BEGIN TRY
DECLARE @EsAdministrador bit = 0;
DECLARE @EsDesarrollador bit = 0;
SELECT
@EsAdministrador = CASE
WHEN R.NombreRol IN ('SuperUsuario', 'Administrador') THEN 1
ELSE 0
END,
@EsDesarrollador = CASE
WHEN R.NombreRol = 'Empresa' THEN 1
ELSE 0
END
FROM dbo.Sis_Usuarios AS U
INNER JOIN dbo.Sis_Roles AS R ON R.CveRol = U.CveRol
WHERE U.CveUsuario = @CveUsuarioEjecuta
AND U.Activo = 1
AND R.Activo = 1;
DECLARE @ValoresPlantilla TABLE
(
CveBitacora bigint NOT NULL,
CveCampo int NOT NULL,
NombreCampoSQL varchar(128) COLLATE Modern_Spanish_CS_AS NOT NULL,
AliasReferencia varchar(128) COLLATE Modern_Spanish_CS_AS NULL,
TipoDatoSQL varchar(128) NULL,
MostrarEnBitacora bit NOT NULL,
ValorAnterior nvarchar(max) COLLATE Modern_Spanish_CS_AS NULL,
ValorNuevo nvarchar(max) COLLATE Modern_Spanish_CS_AS NULL,
ValorAnteriorMostrar nvarchar(max) COLLATE Modern_Spanish_CS_AS NULL,
ValorNuevoMostrar nvarchar(max) COLLATE Modern_Spanish_CS_AS NULL,
Orden int NOT NULL
);
DECLARE @RegistrosPlantilla TABLE
(
CveBitacora bigint NOT NULL PRIMARY KEY,
CveTabla int NOT NULL,
CveTipoMovimiento tinyint NOT NULL
);
DECLARE @ResultadosPlantilla TABLE
(
CveBitacora bigint NOT NULL,
CveCampo int NOT NULL,
ValorAnterior nvarchar(max) COLLATE Modern_Spanish_CS_AS NULL,
ValorNuevo nvarchar(max) COLLATE Modern_Spanish_CS_AS NULL,
Orden int NOT NULL
);
DECLARE @CamposSustituidos TABLE
(
CveBitacora bigint NOT NULL,
CveCampo int NOT NULL,
PRIMARY KEY (CveBitacora, CveCampo)
);
DECLARE @EsLecturaHistorica bit = 1;
INSERT INTO @RegistrosPlantilla(CveBitacora, CveTabla, CveTipoMovimiento)
SELECT B.CveBitacora, B.CveTabla, B.CveTipoMovimiento
FROM dbo.Bit_Bitacora AS B
WHERE
(
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BRCliente
INNER JOIN dbo.Bit_Tablas AS TCliente ON TCliente.CveTabla =
BRCliente.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS CCliente ON CCliente.CveCampo =
BRCliente.CveCampoRelacion
AND CCliente.CveTabla = TCliente.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente =
BRCliente.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BRCliente.CveBitacora = B.CveBitacora
AND BRCliente.VisibleDesarrollador = 1
AND TCliente.NombreTablaSQL = 'Clientes'
AND CCliente.NombreCampoSQL = 'CveCliente'
)
)
)
AND B.CveBitacoraEvento = @CveBitacoraEvento;
IF NOT EXISTS (SELECT 1 FROM @RegistrosPlantilla)
BEGIN
SET @ErrorMostrar = 'No se encontró el evento de bitácora solicitado.';
SET @ErrorTipo = 2;
RETURN;
END;
-- Leer únicamente los campos del evento autorizado; sin encabezados ni relaciones de salida.
INSERT INTO @ValoresPlantilla
(
CveBitacora, CveCampo, NombreCampoSQL, AliasReferencia,
TipoDatoSQL, MostrarEnBitacora, ValorAnterior, ValorNuevo,
ValorAnteriorMostrar, ValorNuevoMostrar, Orden
)
SELECT
R.CveBitacora, C.CveCampo, C.NombreCampoSQL, M.NombreCampoSQL,
C.TipoDatoSQL, C.MostrarEnBitacora, BC.ValorAnterior, BC.ValorNuevo,
BC.ValorAnteriorMostrar, BC.ValorNuevoMostrar, C.CveCampo
FROM @RegistrosPlantilla AS R
INNER JOIN dbo.Bit_BitacoraCampos AS BC ON BC.CveBitacora = R.CveBitacora
INNER JOIN dbo.Bit_Campos AS C ON C.CveCampo = BC.CveCampo
LEFT JOIN dbo.Bit_Campos AS M ON M.CveCampo = C.CveCampoMostrarReferencia
AND M.CveTabla = C.CveTablaReferencia
OPTION (LOOP JOIN, MAXDOP 1);
UPDATE @ValoresPlantilla
SET
ValorAnteriorMostrar = COALESCE(ValorAnteriorMostrar,
CASE
WHEN ValorAnterior IS NULL THEN NULL
WHEN TipoDatoSQL = 'bit' AND ValorAnterior IN (N'0', N'1')
THEN CASE WHEN ValorAnterior = N'1' THEN N'Sí' ELSE N'No' END
WHEN TipoDatoSQL = 'time' AND TRY_CONVERT(time, ValorAnterior) IS NOT NULL
THEN LEFT(CONVERT(varchar(16), TRY_CONVERT(time, ValorAnterior), 108), 5)
END),
ValorNuevoMostrar = COALESCE(ValorNuevoMostrar,
CASE
WHEN ValorNuevo IS NULL THEN NULL
WHEN TipoDatoSQL = 'bit' AND ValorNuevo IN (N'0', N'1')
THEN CASE WHEN ValorNuevo = N'1' THEN N'Sí' ELSE N'No' END
WHEN TipoDatoSQL = 'time' AND TRY_CONVERT(time, ValorNuevo) IS NOT NULL
THEN LEFT(CONVERT(varchar(16), TRY_CONVERT(time, ValorNuevo), 108), 5)
END);
-- Sustitución literal de tokens; nunca se ejecuta el contenido de una plantilla.
DECLARE @RegistroPlantilla bigint;
DECLARE @TablaPlantilla int;
DECLARE @CampoPlantilla int;
DECLARE @TextoPlantilla nvarchar(1000);
DECLARE @MovimientoPlantilla tinyint;
DECLARE @Pendiente nvarchar(max);
DECLARE @AnteriorPlantilla nvarchar(max);
DECLARE @NuevoPlantilla nvarchar(max);
DECLARE @InicioToken int;
DECLARE @FinToken int;
DECLARE @Token nvarchar(128);
DECLARE @CampoToken int;
DECLARE @Coincidencias int;
DECLARE @AnteriorToken nvarchar(max);
DECLARE @NuevoToken nvarchar(max);
DECLARE @Completa bit;
DECLARE @CamposUsados TABLE (CveCampo int NOT NULL PRIMARY KEY);
DECLARE CursorPlantillas CURSOR LOCAL FAST_FORWARD FOR
SELECT R.CveBitacora, R.CveTabla, P.CveCampo, P.Plantilla, R.CveTipoMovimiento
FROM @RegistrosPlantilla AS R
INNER JOIN dbo.Bit_Campos AS P ON P.CveTabla = R.CveTabla
WHERE P.Activo = 1
AND P.MostrarEnBitacora = 1
AND P.Plantilla IS NOT NULL
AND NOT EXISTS
(
SELECT 1
FROM @ValoresPlantilla AS V
WHERE V.CveBitacora = R.CveBitacora AND V.CveCampo = P.CveCampo
)
ORDER BY R.CveBitacora, P.CveCampo;
OPEN CursorPlantillas;
FETCH NEXT FROM CursorPlantillas INTO
@RegistroPlantilla, @TablaPlantilla, @CampoPlantilla,
@TextoPlantilla, @MovimientoPlantilla;
WHILE @@FETCH_STATUS = 0
BEGIN
DELETE FROM @CamposUsados;
SELECT
@Pendiente = @TextoPlantilla,
@AnteriorPlantilla = N'',
@NuevoPlantilla = N'',
@Completa = 1;
WHILE LEN(@Pendiente) > 0
BEGIN
SET @InicioToken = CHARINDEX(N'{', @Pendiente);
IF @InicioToken = 0
BEGIN
IF CHARINDEX(N'}', @Pendiente) > 0
SET @Completa = 0;
SET @AnteriorPlantilla += @Pendiente;
SET @NuevoPlantilla += @Pendiente;
BREAK;
END;
SET @FinToken = CHARINDEX(N'}', @Pendiente, @InicioToken + 1);
IF @FinToken = 0 OR @FinToken - @InicioToken NOT BETWEEN 2 AND 129
OR CHARINDEX(N'}', LEFT(@Pendiente, @InicioToken - 1)) > 0
BEGIN
SET @Completa = 0;
BREAK;
END;
SET @Token = SUBSTRING(@Pendiente, @InicioToken + 1, @FinToken - @InicioToken - 1);
SET @CampoToken = NULL;
SELECT @Coincidencias = COUNT(*), @CampoToken = MIN(CveCampo)
FROM @ValoresPlantilla
WHERE CveBitacora = @RegistroPlantilla
AND NombreCampoSQL = @Token;
IF @Coincidencias = 0
BEGIN
SELECT @Coincidencias = COUNT(*), @CampoToken = MIN(CveCampo)
FROM @ValoresPlantilla
WHERE CveBitacora = @RegistroPlantilla
AND AliasReferencia = @Token;
END;
IF @Coincidencias <> 1 OR EXISTS
(
SELECT 1 FROM dbo.Bit_Campos
WHERE CveCampo = @CampoToken AND Plantilla IS NOT NULL
)
BEGIN
SET @Completa = 0;
BREAK;
END;
-- Una clave de catálogo sin texto histórico no permite reconstruir su nombre anterior.
IF EXISTS
(
SELECT 1
FROM @ValoresPlantilla
WHERE CveBitacora = @RegistroPlantilla AND CveCampo = @CampoToken
AND AliasReferencia IS NOT NULL
AND
(
(ValorAnterior IS NOT NULL AND ValorAnteriorMostrar IS NULL)
OR (ValorNuevo IS NOT NULL AND ValorNuevoMostrar IS NULL)
)
)
BEGIN
SET @Completa = 0;
BREAK;
END;
SELECT
@AnteriorToken = COALESCE(ValorAnteriorMostrar, ValorAnterior, N''),
@NuevoToken = COALESCE(ValorNuevoMostrar, ValorNuevo, N'')
FROM @ValoresPlantilla
WHERE CveBitacora = @RegistroPlantilla AND CveCampo = @CampoToken;
SET @AnteriorPlantilla += LEFT(@Pendiente, @InicioToken - 1) + @AnteriorToken;
SET @NuevoPlantilla += LEFT(@Pendiente, @InicioToken - 1) + @NuevoToken;
SET @Pendiente = SUBSTRING(@Pendiente, @FinToken + 1, LEN(@Pendiente));
IF NOT EXISTS (SELECT 1 FROM @CamposUsados WHERE CveCampo = @CampoToken)
INSERT INTO @CamposUsados(CveCampo) VALUES (@CampoToken);
END;
IF NOT EXISTS (SELECT 1 FROM @CamposUsados)
SET @Completa = 0;
IF @Completa = 1
BEGIN
INSERT INTO @ResultadosPlantilla
(CveBitacora, CveCampo, ValorAnterior, ValorNuevo, Orden)
SELECT
@RegistroPlantilla,
@CampoPlantilla,
CASE WHEN @MovimientoPlantilla = 1 THEN NULL ELSE @AnteriorPlantilla END,
CASE WHEN @MovimientoPlantilla = 3 THEN NULL ELSE @NuevoPlantilla END,
MIN(V.Orden)
FROM @ValoresPlantilla AS V
INNER JOIN @CamposUsados AS U ON U.CveCampo = V.CveCampo
WHERE V.CveBitacora = @RegistroPlantilla;
INSERT INTO @CamposSustituidos(CveBitacora, CveCampo)
SELECT @RegistroPlantilla, U.CveCampo
FROM @CamposUsados AS U
INNER JOIN @ValoresPlantilla AS V ON V.CveBitacora = @RegistroPlantilla
AND V.CveCampo = U.CveCampo
WHERE V.MostrarEnBitacora = 0
AND NOT EXISTS
(
SELECT 1 FROM @CamposSustituidos AS S
WHERE S.CveBitacora = @RegistroPlantilla AND S.CveCampo = U.CveCampo
);
END
ELSE IF @EsLecturaHistorica = 0
BEGIN
CLOSE CursorPlantillas;
DEALLOCATE CursorPlantillas;
SET @ErrorMostrar = 'No se pudo formar la plantilla de bitácora: revise sus campos y valores mostrables.';
SET @ErrorTipo = 2;
RETURN;
END;
FETCH NEXT FROM CursorPlantillas INTO
@RegistroPlantilla, @TablaPlantilla, @CampoPlantilla,
@TextoPlantilla, @MovimientoPlantilla;
END;
CLOSE CursorPlantillas;
DEALLOCATE CursorPlantillas;
;WITH Detalle AS
(
SELECT V.CveBitacora, V.CveCampo, V.Orden,
COALESCE(V.ValorAnteriorMostrar, V.ValorAnterior) AS ValorAnteriorMostrar,
COALESCE(V.ValorNuevoMostrar, V.ValorNuevo) AS ValorNuevoMostrar
FROM @ValoresPlantilla AS V
WHERE (@EsAdministrador = 1 OR V.MostrarEnBitacora = 1)
AND NOT EXISTS
(
SELECT 1 FROM @CamposSustituidos AS S
WHERE S.CveBitacora = V.CveBitacora AND S.CveCampo = V.CveCampo
)
UNION ALL
SELECT CveBitacora, CveCampo, Orden, ValorAnterior, ValorNuevo
FROM @ResultadosPlantilla
)
SELECT
D.CveBitacora,
CONVERT(int, ROW_NUMBER() OVER
(ORDER BY D.CveBitacora, D.Orden, D.CveCampo)) AS Orden,
CASE WHEN @EsAdministrador = 1
THEN COALESCE(B.LlaveRegistroTexto, CONVERT(nvarchar(250), B.LlaveRegistro))
ELSE NULL END AS LlaveRegistro,
C.NombreMostrar,
D.ValorAnteriorMostrar,
D.ValorNuevoMostrar
FROM Detalle AS D
INNER JOIN dbo.Bit_Bitacora AS B ON B.CveBitacora = D.CveBitacora
INNER JOIN dbo.Bit_Campos AS C ON C.CveCampo = D.CveCampo
ORDER BY D.CveBitacora, D.Orden, D.CveCampo
OPTION (LOOP JOIN, MAXDOP 1, RECOMPILE);
SET @Return = 1;
END TRY
BEGIN CATCH
SET @ErrorMostrar = 'No fue posible consultar el detalle de la bitácora. Contacte a Sistemas.';
SET @ErrorTipo = 1;
SET @Return = 0;
DECLARE @ErrorTecnico nvarchar(2048) = CONCAT(
'Número: ', ERROR_NUMBER(),
'; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Bit_BitacoraEventoObtener'),
'; Línea: ', ERROR_LINE(),
'; Detalle: ', ERROR_MESSAGE()
);
RAISERROR(N'%s', 10, 1, @ErrorTecnico);
END CATCH;
END;
GO
CREATE OR ALTER PROCEDURE dbo.PA_Bit_BitacoraList
@NombreTablaSQL varchar(128) = NULL,
@LlaveRegistro nvarchar(250) = NULL,
@CveUsuarioFiltro int = NULL,
@FechaInicio datetime = NULL,
@FechaFin datetime = NULL,
@Modulo varchar(150) = NULL,
@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT
@ErrorMostrar = NULL,
@ErrorTipo = 0,
@Return = 0;
BEGIN TRY
DECLARE @EsAdministrador bit = 0;
DECLARE @EsDesarrollador bit = 0;
SELECT
@EsAdministrador = CASE
WHEN R.NombreRol IN ('SuperUsuario', 'Administrador') THEN 1
ELSE 0
END,
@EsDesarrollador = CASE
WHEN R.NombreRol = 'Empresa' THEN 1
ELSE 0
END
FROM dbo.Sis_Usuarios AS U
INNER JOIN dbo.Sis_Roles AS R ON R.CveRol = U.CveRol
WHERE U.CveUsuario = @CveUsuarioEjecuta
AND U.Activo = 1
AND R.Activo = 1;
SELECT
B.CveBitacora,
B.CveTabla,
T.NombreTablaSQL,
T.NombreMostrar AS NombreTabla,
B.CveTipoMovimiento,
M.Nombre AS TipoMovimiento,
A.NombreAccion,
B.CveUsuarioEjecuta,
B.CveUsuarioAutoriza,
B.FechaAutorizacion,
B.LlaveRegistro,
B.DescripcionMovimiento,
B.FechaMovimiento,
B.DireccionIP,
B.NombreEquipo,
B.Modulo
FROM (
SELECT R.CveBitacora, R.CveTabla, R.CveTipoMovimiento,
COALESCE(R.LlaveRegistroTexto, CONVERT(nvarchar(250), R.LlaveRegistro)) AS LlaveRegistro,
E.CveDefinicionAccion, E.CveUsuarioEjecuta, E.CveUsuarioAutoriza, E.FechaAutorizacion, E.FechaMovimiento, E.DireccionIP, E.NombreEquipo, E.Modulo,
CASE WHEN @EsAdministrador = 1 OR NOT EXISTS
(
SELECT 1
FROM dbo.Bit_Bitacora AS R2
WHERE R2.CveBitacoraEvento = E.CveBitacoraEvento
AND NOT ((
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BRCliente
INNER JOIN dbo.Bit_Tablas AS TCliente ON TCliente.CveTabla =
BRCliente.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS CCliente ON CCliente.CveCampo =
BRCliente.CveCampoRelacion
AND CCliente.CveTabla = TCliente.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente =
BRCliente.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BRCliente.CveBitacora = R2.CveBitacora
AND BRCliente.VisibleDesarrollador = 1
AND TCliente.NombreTablaSQL = 'Clientes'
AND CCliente.NombreCampoSQL = 'CveCliente'
)
)
))
) THEN E.DescripcionMovimiento
ELSE N'Operación con registros de acceso restringido.' END AS DescripcionMovimiento
FROM dbo.Bit_Bitacora AS R
INNER JOIN dbo.Bit_BitacoraEventos AS E ON E.CveBitacoraEvento = R.CveBitacoraEvento
) AS B
INNER JOIN dbo.Bit_Tablas AS T ON T.CveTabla = B.CveTabla
INNER JOIN dbo.Bit_TiposMovimiento AS M ON M.CveTipoMovimiento = B.CveTipoMovimiento
LEFT JOIN dbo.Bit_DefinicionesAccion AS A ON A.CveDefinicionAccion = B.CveDefinicionAccion
WHERE (@NombreTablaSQL IS NULL OR T.NombreTablaSQL = @NombreTablaSQL COLLATE Modern_Spanish_CS_AS)
AND (@LlaveRegistro IS NULL OR B.LlaveRegistro = @LlaveRegistro COLLATE Modern_Spanish_CS_AS)
AND (@CveUsuarioFiltro IS NULL OR B.CveUsuarioEjecuta = @CveUsuarioFiltro)
AND (@FechaInicio IS NULL OR B.FechaMovimiento >= @FechaInicio)
AND
(
@FechaFin IS NULL
OR B.FechaMovimiento < DATEADD(day, 1, CONVERT(date, @FechaFin))
)
AND (@Modulo IS NULL OR B.Modulo = @Modulo COLLATE Modern_Spanish_CS_AS)
AND
(
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BR
INNER JOIN dbo.Bit_Tablas AS RT ON RT.CveTabla = BR.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS RC ON RC.CveCampo = BR.CveCampoRelacion
AND RC.CveTabla = RT.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente = BR.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BR.CveBitacora = B.CveBitacora
AND BR.VisibleDesarrollador = 1
AND RT.NombreTablaSQL = 'Clientes'
AND RC.NombreCampoSQL = 'CveCliente'
)
)
)
ORDER BY
B.FechaMovimiento DESC,
B.CveBitacora DESC;
SET @Return = 1;
END TRY
BEGIN CATCH
SET @ErrorMostrar = 'Ocurrió un error al consultar la bitácora; favor de contactar a Sistemas.';
SET @ErrorTipo = 1;
SET @Return = 0;
DECLARE @ErrorTecnico nvarchar(2048) = CONCAT(
'Número: ', ERROR_NUMBER(),
'; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Bit_BitacoraList'),
'; Línea: ', ERROR_LINE(),
'; Detalle: ', ERROR_MESSAGE()
);
RAISERROR(N'%s', 10, 1, @ErrorTecnico);
END CATCH;
END;
GO
CREATE OR ALTER PROCEDURE dbo.PA_Bit_BitacoraListByRelations
@RelacionesXml xml = NULL,
@RelacionesMostrarXml xml = NULL,
@RegistrosOmitidos int,
@RegistrosPorPagina int,
@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT
@ErrorMostrar = NULL,
@ErrorTipo = 0,
@Return = 0;
BEGIN TRY
IF @RegistrosOmitidos < 0 OR @RegistrosPorPagina <= 0
BEGIN
SET @ErrorMostrar = 'Los datos de paginación no son válidos.';
SET @ErrorTipo = 2;
RETURN;
END;
DECLARE @EsAdministrador bit = 0;
DECLARE @EsDesarrollador bit = 0;
SELECT
@EsAdministrador = CASE
WHEN R.NombreRol IN ('SuperUsuario', 'Administrador') THEN 1
ELSE 0
END,
@EsDesarrollador = CASE
WHEN R.NombreRol = 'Empresa' THEN 1
ELSE 0
END
FROM dbo.Sis_Usuarios AS U
INNER JOIN dbo.Sis_Roles AS R ON R.CveRol = U.CveRol
WHERE U.CveUsuario = @CveUsuarioEjecuta
AND U.Activo = 1
AND R.Activo = 1;
DECLARE @Filtros TABLE
(
Orden int NOT NULL PRIMARY KEY,
NombreTablaSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreCampoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
Valor nvarchar(250)
COLLATE Modern_Spanish_CS_AS NOT NULL,
SoloExistencia bit NOT NULL
);
IF @RelacionesXml IS NOT NULL
BEGIN
INSERT INTO @Filtros
(
Orden,
NombreTablaSQL,
NombreCampoSQL,
Valor,
SoloExistencia
)
SELECT
R.value('@Orden', 'int'),
R.value('@Tabla', 'varchar(128)'),
R.value('@Campo', 'varchar(128)'),
R.value('@Valor', 'nvarchar(250)'),
CASE
WHEN R.exist('@SoloExistencia') = 1
THEN R.value('@SoloExistencia', 'bit')
ELSE 0
END
FROM @RelacionesXml.nodes('/Relaciones/Relacion') AS X(R);
END;
DECLARE @FiltrosResueltos TABLE
(
Orden int NOT NULL PRIMARY KEY,
CveTabla int NOT NULL,
CveCampo int NOT NULL,
TipoDatoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
Valor nvarchar(250)
COLLATE Modern_Spanish_CS_AS NOT NULL,
SoloExistencia bit NOT NULL,
EsEntero bit NOT NULL
);
INSERT INTO @FiltrosResueltos
(
Orden,
CveTabla,
CveCampo,
TipoDatoSQL,
Valor,
SoloExistencia,
EsEntero
)
SELECT
F.Orden,
T.CveTabla,
C.CveCampo,
C.TipoDatoSQL,
F.Valor,
F.SoloExistencia,
CASE
WHEN C.TipoDatoSQL IN
(
'tinyint',
'smallint',
'int',
'bigint'
) THEN 1
ELSE 0
END
FROM @Filtros AS F
INNER JOIN dbo.Bit_Tablas AS T ON T.NombreTablaSQL = F.NombreTablaSQL
AND T.Activo = 1
INNER JOIN dbo.Bit_Campos AS C ON C.CveTabla = T.CveTabla
AND C.NombreCampoSQL = F.NombreCampoSQL
AND C.Activo = 1
INNER JOIN sys.schemas AS SF ON SF.name = 'dbo'
INNER JOIN sys.tables AS TF ON TF.schema_id = SF.schema_id
AND TF.name COLLATE Modern_Spanish_CS_AS = T.NombreTablaSQL
INNER JOIN sys.columns AS CF ON CF.object_id = TF.object_id
AND CF.name COLLATE Modern_Spanish_CS_AS = C.NombreCampoSQL
WHERE C.TipoDatoSQL IS NOT NULL;
IF (SELECT COUNT(1) FROM @Filtros) <>
(SELECT COUNT(1) FROM @FiltrosResueltos)
BEGIN
SET @ErrorMostrar = 'Una relación utiliza una tabla o campo que no está configurado en la bitácora.';
SET @ErrorTipo = 2;
RETURN;
END;
IF EXISTS
(
SELECT 1
FROM @FiltrosResueltos
WHERE SoloExistencia = 0
AND EsEntero = 1
AND TRY_CONVERT(bigint, Valor) IS NULL
)
BEGIN
SET @ErrorMostrar = 'El valor de una relación numérica no es válido.';
SET @ErrorTipo = 2;
RETURN;
END;
DECLARE @RelacionesMostrar TABLE
(
Orden int NOT NULL,
NombreTablaSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreCampoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL
);
IF @RelacionesMostrarXml IS NOT NULL
BEGIN
INSERT INTO @RelacionesMostrar
(
Orden,
NombreTablaSQL,
NombreCampoSQL
)
SELECT
R.value('@Orden', 'int'),
R.value('@Tabla', 'varchar(128)'),
R.value('@Campo', 'varchar(128)')
FROM @RelacionesMostrarXml.nodes('/RelacionesMostrar/Relacion') AS X(R);
END;
IF (SELECT COUNT(1) FROM @RelacionesMostrar) > 10
OR EXISTS
(
SELECT 1
FROM @RelacionesMostrar
WHERE Orden <= 0
)
OR EXISTS
(
SELECT Orden
FROM @RelacionesMostrar
GROUP BY Orden
HAVING COUNT(1) > 1
)
OR EXISTS
(
SELECT
NombreTablaSQL,
NombreCampoSQL
FROM @RelacionesMostrar
GROUP BY
NombreTablaSQL,
NombreCampoSQL
HAVING COUNT(1) > 1
)
BEGIN
SET @ErrorMostrar = 'La configuración de relaciones a mostrar no es válida.';
SET @ErrorTipo = 2;
RETURN;
END;
DECLARE @RelacionesMostrarResueltas TABLE
(
Orden int NOT NULL PRIMARY KEY,
CveTabla int NOT NULL,
NombreTablaSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreTabla varchar(150)
COLLATE Modern_Spanish_CS_AS NOT NULL,
CveCampoLlave int NOT NULL,
NombreCampoLlaveSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
CveCampoMostrar int NOT NULL,
NombreCampoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreCampo varchar(150)
COLLATE Modern_Spanish_CS_AS NOT NULL
);
INSERT INTO @RelacionesMostrarResueltas
(
Orden,
CveTabla,
NombreTablaSQL,
NombreTabla,
CveCampoLlave,
NombreCampoLlaveSQL,
CveCampoMostrar,
NombreCampoSQL,
NombreCampo
)
SELECT
R.Orden,
T.CveTabla,
T.NombreTablaSQL,
T.NombreMostrar,
CL.CveCampo,
CL.NombreCampoSQL,
CM.CveCampo,
CM.NombreCampoSQL,
CM.NombreMostrar
FROM @RelacionesMostrar AS R
INNER JOIN dbo.Bit_Tablas AS T ON T.NombreTablaSQL = R.NombreTablaSQL
AND T.Activo = 1
AND T.NombreCampoLlaveSQL IS NOT NULL
INNER JOIN dbo.Bit_Campos AS CL ON CL.CveTabla = T.CveTabla
AND CL.NombreCampoSQL = T.NombreCampoLlaveSQL
AND CL.Activo = 1
INNER JOIN dbo.Bit_Campos AS CM ON CM.CveTabla = T.CveTabla
AND CM.NombreCampoSQL = R.NombreCampoSQL
AND CM.MostrarEnBitacora = 1
AND CM.Activo = 1
INNER JOIN sys.schemas AS SC ON SC.name = 'dbo'
INNER JOIN sys.tables AS ST ON ST.schema_id = SC.schema_id
AND ST.name COLLATE Modern_Spanish_CS_AS = T.NombreTablaSQL
INNER JOIN sys.columns AS SCL ON SCL.object_id = ST.object_id
AND SCL.name COLLATE Modern_Spanish_CS_AS = CL.NombreCampoSQL
INNER JOIN sys.columns AS SCM ON SCM.object_id = ST.object_id
AND SCM.name COLLATE Modern_Spanish_CS_AS = CM.NombreCampoSQL;
IF (SELECT COUNT(1) FROM @RelacionesMostrar) <>
(SELECT COUNT(1) FROM @RelacionesMostrarResueltas)
BEGIN
SET @ErrorMostrar = 'Una relación a mostrar utiliza una tabla o campo no permitido.';
SET @ErrorTipo = 2;
RETURN;
END;
CREATE TABLE #BitacorasCoincidentes
(
CveBitacora bigint NOT NULL PRIMARY KEY,
FechaMovimiento datetime NOT NULL
);
INSERT INTO #BitacorasCoincidentes
(
CveBitacora,
FechaMovimiento
)
SELECT
B.CveBitacora,
B.FechaMovimiento
FROM (
SELECT R.CveBitacora, R.CveTabla, R.CveTipoMovimiento,
COALESCE(R.LlaveRegistroTexto, CONVERT(nvarchar(250), R.LlaveRegistro)) AS LlaveRegistro,
E.CveDefinicionAccion, E.CveUsuarioEjecuta, E.CveUsuarioAutoriza, E.FechaAutorizacion, E.FechaMovimiento, E.DireccionIP, E.NombreEquipo, E.Modulo,
CASE WHEN @EsAdministrador = 1 OR NOT EXISTS
(
SELECT 1
FROM dbo.Bit_Bitacora AS R2
WHERE R2.CveBitacoraEvento = E.CveBitacoraEvento
AND NOT ((
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BRCliente
INNER JOIN dbo.Bit_Tablas AS TCliente ON TCliente.CveTabla =
BRCliente.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS CCliente ON CCliente.CveCampo =
BRCliente.CveCampoRelacion
AND CCliente.CveTabla = TCliente.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente =
BRCliente.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BRCliente.CveBitacora = R2.CveBitacora
AND BRCliente.VisibleDesarrollador = 1
AND TCliente.NombreTablaSQL = 'Clientes'
AND CCliente.NombreCampoSQL = 'CveCliente'
)
)
))
) THEN E.DescripcionMovimiento
ELSE N'Operación con registros de acceso restringido.' END AS DescripcionMovimiento
FROM dbo.Bit_Bitacora AS R
INNER JOIN dbo.Bit_BitacoraEventos AS E ON E.CveBitacoraEvento = R.CveBitacoraEvento
) AS B
WHERE
(
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BRCliente
INNER JOIN dbo.Bit_Tablas AS TCliente ON TCliente.CveTabla =
BRCliente.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS CCliente ON CCliente.CveCampo =
BRCliente.CveCampoRelacion
AND CCliente.CveTabla = TCliente.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente =
BRCliente.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BRCliente.CveBitacora = B.CveBitacora
AND BRCliente.VisibleDesarrollador = 1
AND TCliente.NombreTablaSQL = 'Clientes'
AND CCliente.NombreCampoSQL = 'CveCliente'
)
)
)
AND
(
@EsDesarrollador = 0
OR NOT EXISTS
(
SELECT 1
FROM @FiltrosResueltos AS FCliente
INNER JOIN dbo.Bit_Tablas AS TClienteFiltro ON TClienteFiltro.CveTabla = FCliente.CveTabla
INNER JOIN dbo.Bit_Campos AS CClienteFiltro ON CClienteFiltro.CveCampo = FCliente.CveCampo
AND CClienteFiltro.CveTabla =
TClienteFiltro.CveTabla
WHERE TClienteFiltro.NombreTablaSQL = 'Clientes'
AND CClienteFiltro.NombreCampoSQL = 'CveCliente'
AND FCliente.SoloExistencia = 0
AND NOT EXISTS
(
SELECT 1
FROM dbo.Sis_UsuariosClientes AS UCClienteFiltro
WHERE UCClienteFiltro.CveUsuario =
@CveUsuarioEjecuta
AND UCClienteFiltro.CveCliente =
TRY_CONVERT(bigint, FCliente.Valor)
AND UCClienteFiltro.Activo = 1
)
)
)
AND NOT EXISTS
(
SELECT 1
FROM @FiltrosResueltos AS F
WHERE NOT EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BR
WHERE BR.CveBitacora = B.CveBitacora
AND BR.CveTablaRelacionada = F.CveTabla
AND BR.CveCampoRelacion = F.CveCampo
AND
(
@EsAdministrador = 1
OR BR.VisibleDesarrollador = 1
)
AND
(
F.SoloExistencia = 1
OR
(
(
F.EsEntero = 1
AND BR.ValorRelacionNumero =
TRY_CONVERT(bigint, F.Valor)
)
OR
(
F.EsEntero = 0
AND BR.ValorRelacionTexto =
F.Valor COLLATE Modern_Spanish_CS_AS
)
)
)
)
);
DECLARE @TotalRegistros int;
SELECT @TotalRegistros = COUNT(DISTINCT CveBitacora)
FROM #BitacorasCoincidentes;
CREATE TABLE #BitacorasPagina
(
CveBitacora bigint NOT NULL PRIMARY KEY,
Orden int NOT NULL
);
INSERT INTO #BitacorasPagina
(
CveBitacora,
Orden
)
SELECT
C.CveBitacora,
ROW_NUMBER() OVER
(
ORDER BY
C.FechaMovimiento DESC,
C.CveBitacora DESC
)
FROM #BitacorasCoincidentes AS C
ORDER BY
C.FechaMovimiento DESC,
C.CveBitacora DESC
OFFSET @RegistrosOmitidos ROWS
FETCH NEXT @RegistrosPorPagina ROWS ONLY;
SELECT @TotalRegistros AS TotalRegistros;
SELECT
B.CveBitacora,
B.CveTabla,
T.NombreTablaSQL,
T.NombreMostrar AS NombreTabla,
B.CveTipoMovimiento,
M.Nombre AS TipoMovimiento,
B.CveDefinicionAccion,
A.NombreAccion,
A.DescripcionAccion,
B.CveUsuarioEjecuta,
COALESCE(
NULLIF(U.NombreUsuario, ''),
CONCAT('(', B.CveUsuarioEjecuta, ') Eliminado')
) AS NombreUsuarioEjecuta,
B.CveUsuarioAutoriza,
B.FechaAutorizacion,
B.LlaveRegistro,
B.DescripcionMovimiento,
B.FechaMovimiento,
B.DireccionIP,
B.NombreEquipo,
B.Modulo
FROM #BitacorasPagina AS P
INNER JOIN (
SELECT R.CveBitacora, R.CveTabla, R.CveTipoMovimiento,
COALESCE(R.LlaveRegistroTexto, CONVERT(nvarchar(250), R.LlaveRegistro)) AS LlaveRegistro,
E.CveDefinicionAccion, E.CveUsuarioEjecuta, E.CveUsuarioAutoriza, E.FechaAutorizacion, E.FechaMovimiento, E.DireccionIP, E.NombreEquipo, E.Modulo,
CASE WHEN @EsAdministrador = 1 OR NOT EXISTS
(
SELECT 1
FROM dbo.Bit_Bitacora AS R2
WHERE R2.CveBitacoraEvento = E.CveBitacoraEvento
AND NOT ((
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BRCliente
INNER JOIN dbo.Bit_Tablas AS TCliente ON TCliente.CveTabla =
BRCliente.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS CCliente ON CCliente.CveCampo =
BRCliente.CveCampoRelacion
AND CCliente.CveTabla = TCliente.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente =
BRCliente.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BRCliente.CveBitacora = R2.CveBitacora
AND BRCliente.VisibleDesarrollador = 1
AND TCliente.NombreTablaSQL = 'Clientes'
AND CCliente.NombreCampoSQL = 'CveCliente'
)
)
))
) THEN E.DescripcionMovimiento
ELSE N'Operación con registros de acceso restringido.' END AS DescripcionMovimiento
FROM dbo.Bit_Bitacora AS R
INNER JOIN dbo.Bit_BitacoraEventos AS E ON E.CveBitacoraEvento = R.CveBitacoraEvento
) AS B
ON B.CveBitacora = P.CveBitacora
INNER JOIN dbo.Bit_Tablas AS T ON T.CveTabla = B.CveTabla
INNER JOIN dbo.Bit_TiposMovimiento AS M ON M.CveTipoMovimiento = B.CveTipoMovimiento
LEFT JOIN dbo.Bit_DefinicionesAccion AS A ON A.CveDefinicionAccion = B.CveDefinicionAccion
LEFT JOIN dbo.Sis_Usuarios AS U ON U.CveUsuario = B.CveUsuarioEjecuta
ORDER BY P.Orden;
CREATE TABLE #CamposPagina
(
OrdenPagina int NOT NULL,
CveBitacoraCampo bigint NOT NULL PRIMARY KEY,
CveBitacora bigint NOT NULL,
CveCampo int NOT NULL,
NombreCampoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreMostrar varchar(150)
COLLATE Modern_Spanish_CS_AS NOT NULL,
ValorAnterior nvarchar(max)
COLLATE Modern_Spanish_CS_AS NULL,
ValorNuevo nvarchar(max)
COLLATE Modern_Spanish_CS_AS NULL,
ValorAnteriorMostrar nvarchar(max)
COLLATE Modern_Spanish_CS_AS NULL,
ValorNuevoMostrar nvarchar(max)
COLLATE Modern_Spanish_CS_AS NULL
);
INSERT INTO #CamposPagina
(
OrdenPagina,
CveBitacoraCampo,
CveBitacora,
CveCampo,
NombreCampoSQL,
NombreMostrar,
ValorAnterior,
ValorNuevo,
ValorAnteriorMostrar,
ValorNuevoMostrar
)
SELECT
P.Orden,
BC.CveBitacoraCampo,
BC.CveBitacora,
BC.CveCampo,
C.NombreCampoSQL,
C.NombreMostrar,
BC.ValorAnterior,
BC.ValorNuevo,
BC.ValorAnterior,
BC.ValorNuevo
FROM #BitacorasPagina AS P
INNER JOIN dbo.Bit_BitacoraCampos AS BC ON BC.CveBitacora = P.CveBitacora
INNER JOIN dbo.Bit_Campos AS C ON C.CveCampo = BC.CveCampo
WHERE @EsAdministrador = 1
OR C.MostrarEnBitacora = 1;
DECLARE @CveCampoOrigenReferencia int;
DECLARE @NombreTablaReferencia varchar(128);
DECLARE @NombreCampoLlaveReferencia varchar(128);
DECLARE @NombreCampoMostrarReferencia varchar(128);
DECLARE @SqlCampoReferencia nvarchar(max);
-- Los identificadores del SQL dinámico salen únicamente de metadatos
-- activos y se verifican contra sys.tables/sys.columns antes de usarse.
DECLARE CursorCamposReferencia CURSOR LOCAL FAST_FORWARD FOR
SELECT DISTINCT
CO.CveCampo,
TR.NombreTablaSQL,
CL.NombreCampoSQL,
CM.NombreCampoSQL
FROM #CamposPagina AS CP
INNER JOIN dbo.Bit_Campos AS CO ON CO.CveCampo = CP.CveCampo
AND CO.Activo = 1
INNER JOIN dbo.Bit_Tablas AS TR ON TR.CveTabla = CO.CveTablaReferencia
AND TR.Activo = 1
AND TR.NombreCampoLlaveSQL IS NOT NULL
INNER JOIN dbo.Bit_Campos AS CL ON CL.CveTabla = TR.CveTabla
AND CL.NombreCampoSQL = TR.NombreCampoLlaveSQL
AND CL.Activo = 1
INNER JOIN dbo.Bit_Campos AS CM ON CM.CveCampo = CO.CveCampoMostrarReferencia
AND CM.CveTabla = TR.CveTabla
AND CM.MostrarEnBitacora = 1
AND CM.Activo = 1
INNER JOIN sys.schemas AS SC ON SC.name = 'dbo'
INNER JOIN sys.tables AS ST ON ST.schema_id = SC.schema_id
AND ST.name COLLATE Modern_Spanish_CS_AS = TR.NombreTablaSQL
INNER JOIN sys.columns AS SCL ON SCL.object_id = ST.object_id
AND SCL.name COLLATE Modern_Spanish_CS_AS = CL.NombreCampoSQL
INNER JOIN sys.columns AS SCM ON SCM.object_id = ST.object_id
AND SCM.name COLLATE Modern_Spanish_CS_AS = CM.NombreCampoSQL;
OPEN CursorCamposReferencia;
FETCH NEXT FROM CursorCamposReferencia INTO
@CveCampoOrigenReferencia,
@NombreTablaReferencia,
@NombreCampoLlaveReferencia,
@NombreCampoMostrarReferencia;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SqlCampoReferencia = N'
UPDATE CP
SET
CP.ValorAnteriorMostrar = CASE
WHEN CP.ValorAnterior IS NULL THEN NULL
WHEN VA.' + QUOTENAME(@NombreCampoLlaveReferencia) + N' IS NULL
THEN CONCAT(N''('', CP.ValorAnterior, N'') Eliminada'')
WHEN NULLIF(CONVERT(nvarchar(max), VA.' + QUOTENAME(@NombreCampoMostrarReferencia) + N'), N'''') IS NULL
THEN CONCAT(N''('', CP.ValorAnterior, N'')'')
ELSE CONVERT(nvarchar(max), VA.' + QUOTENAME(@NombreCampoMostrarReferencia) + N')
END,
CP.ValorNuevoMostrar = CASE
WHEN CP.ValorNuevo IS NULL THEN NULL
WHEN VN.' + QUOTENAME(@NombreCampoLlaveReferencia) + N' IS NULL
THEN CONCAT(N''('', CP.ValorNuevo, N'') Eliminada'')
WHEN NULLIF(CONVERT(nvarchar(max), VN.' + QUOTENAME(@NombreCampoMostrarReferencia) + N'), N'''') IS NULL
THEN CONCAT(N''('', CP.ValorNuevo, N'')'')
ELSE CONVERT(nvarchar(max), VN.' + QUOTENAME(@NombreCampoMostrarReferencia) + N')
END
FROM #CamposPagina AS CP
LEFT JOIN dbo.' + QUOTENAME(@NombreTablaReferencia) + N' AS VA ON CONVERT(nvarchar(250), VA.' + QUOTENAME(@NombreCampoLlaveReferencia) + N')
COLLATE Modern_Spanish_CS_AS =
CP.ValorAnterior COLLATE Modern_Spanish_CS_AS
LEFT JOIN dbo.' + QUOTENAME(@NombreTablaReferencia) + N' AS VN ON CONVERT(nvarchar(250), VN.' + QUOTENAME(@NombreCampoLlaveReferencia) + N')
COLLATE Modern_Spanish_CS_AS =
CP.ValorNuevo COLLATE Modern_Spanish_CS_AS
WHERE CP.CveCampo = @CveCampoOrigen;';
EXEC sys.sp_executesql
@SqlCampoReferencia,
N'@CveCampoOrigen int',
@CveCampoOrigen = @CveCampoOrigenReferencia;
FETCH NEXT FROM CursorCamposReferencia INTO
@CveCampoOrigenReferencia,
@NombreTablaReferencia,
@NombreCampoLlaveReferencia,
@NombreCampoMostrarReferencia;
END;
CLOSE CursorCamposReferencia;
DEALLOCATE CursorCamposReferencia;
SELECT
CveBitacoraCampo,
CveBitacora,
CveCampo,
NombreCampoSQL,
NombreMostrar,
ValorAnterior,
ValorNuevo,
ValorAnteriorMostrar,
ValorNuevoMostrar
FROM #CamposPagina
ORDER BY
OrdenPagina,
CveBitacoraCampo;
SELECT
BR.CveBitacoraRelacion,
BR.CveBitacora,
BR.CveTipoRelacion,
TR.Nombre AS TipoRelacion,
BR.CveTablaRelacionada,
T.NombreTablaSQL,
BR.CveCampoRelacion,
C.NombreCampoSQL,
BR.LlaveRegistroRelacionada,
BR.ValorRelacionNumero,
BR.ValorRelacionTexto,
BR.VisibleDesarrollador,
BR.DescripcionRelacion
FROM #BitacorasPagina AS P
INNER JOIN dbo.Bit_BitacoraRelaciones AS BR ON BR.CveBitacora = P.CveBitacora
INNER JOIN dbo.Bit_TiposRelacion AS TR ON TR.CveTipoRelacion = BR.CveTipoRelacion
INNER JOIN dbo.Bit_Tablas AS T ON T.CveTabla = BR.CveTablaRelacionada
LEFT JOIN dbo.Bit_Campos AS C ON C.CveCampo = BR.CveCampoRelacion
AND C.CveTabla = T.CveTabla
WHERE @EsAdministrador = 1
OR BR.VisibleDesarrollador = 1
ORDER BY
P.Orden,
BR.CveBitacoraRelacion;
CREATE TABLE #RelacionesVisuales
(
CveBitacora bigint NOT NULL,
Orden int NOT NULL,
NombreTablaSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreTabla varchar(150)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreCampoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreCampo varchar(150)
COLLATE Modern_Spanish_CS_AS NOT NULL,
ValorClave nvarchar(250)
COLLATE Modern_Spanish_CS_AS NOT NULL,
ValorMostrar nvarchar(max)
COLLATE Modern_Spanish_CS_AS NOT NULL
);
DECLARE @OrdenRelacionMostrar int;
DECLARE @CveTablaRelacionMostrar int;
DECLARE @NombreTablaSQLRelacionMostrar varchar(128);
DECLARE @NombreTablaRelacionMostrar varchar(150);
DECLARE @CveCampoLlaveRelacionMostrar int;
DECLARE @NombreCampoLlaveRelacionMostrar varchar(128);
DECLARE @NombreCampoSQLRelacionMostrar varchar(128);
DECLARE @NombreCampoRelacionMostrar varchar(150);
DECLARE @SqlRelacionMostrar nvarchar(max);
-- Tabla, llave y campo visible ya fueron resueltos contra la allowlist
-- de Bit_Tablas/Bit_Campos y se delimitan nuevamente con QUOTENAME.
DECLARE CursorRelacionesMostrar CURSOR LOCAL FAST_FORWARD FOR
SELECT
Orden,
CveTabla,
NombreTablaSQL,
NombreTabla,
CveCampoLlave,
NombreCampoLlaveSQL,
NombreCampoSQL,
NombreCampo
FROM @RelacionesMostrarResueltas
ORDER BY Orden;
OPEN CursorRelacionesMostrar;
FETCH NEXT FROM CursorRelacionesMostrar INTO
@OrdenRelacionMostrar,
@CveTablaRelacionMostrar,
@NombreTablaSQLRelacionMostrar,
@NombreTablaRelacionMostrar,
@CveCampoLlaveRelacionMostrar,
@NombreCampoLlaveRelacionMostrar,
@NombreCampoSQLRelacionMostrar,
@NombreCampoRelacionMostrar;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SqlRelacionMostrar = N'
INSERT INTO #RelacionesVisuales
(
CveBitacora,
Orden,
NombreTablaSQL,
NombreTabla,
NombreCampoSQL,
NombreCampo,
ValorClave,
ValorMostrar
)
SELECT
BR.CveBitacora,
@Orden,
@NombreTablaSQL,
@NombreTabla,
@NombreCampoSQL,
@NombreCampo,
BR.LlaveRegistroRelacionada,
CASE
WHEN V.' + QUOTENAME(@NombreCampoLlaveRelacionMostrar) + N' IS NULL
THEN CONCAT(N''('', BR.LlaveRegistroRelacionada, N'') Eliminada'')
WHEN NULLIF(CONVERT(nvarchar(max), V.' + QUOTENAME(@NombreCampoSQLRelacionMostrar) + N'), N'''') IS NULL
THEN CONCAT(N''('', BR.LlaveRegistroRelacionada, N'')'')
ELSE CONVERT(nvarchar(max), V.' + QUOTENAME(@NombreCampoSQLRelacionMostrar) + N')
END
FROM #BitacorasPagina AS P
INNER JOIN dbo.Bit_BitacoraRelaciones AS BR ON BR.CveBitacora = P.CveBitacora
INNER JOIN dbo.Bit_Bitacora AS B
ON B.CveBitacora = P.CveBitacora
LEFT JOIN dbo.' + QUOTENAME(@NombreTablaSQLRelacionMostrar) + N' AS V ON CONVERT(nvarchar(250), V.' + QUOTENAME(@NombreCampoLlaveRelacionMostrar) + N')
COLLATE Modern_Spanish_CS_AS =
BR.LlaveRegistroRelacionada COLLATE Modern_Spanish_CS_AS
WHERE BR.CveTablaRelacionada = @CveTabla
AND BR.CveCampoRelacion = @CveCampoLlave
AND NOT
(
BR.CveTipoRelacion = 1
AND BR.CveTablaRelacionada = B.CveTabla
)
AND
(
@EsAdministrador = 1
OR BR.VisibleDesarrollador = 1
);';
EXEC sys.sp_executesql
@SqlRelacionMostrar,
N'@Orden int,
@NombreTablaSQL varchar(128),
@NombreTabla varchar(150),
@NombreCampoSQL varchar(128),
@NombreCampo varchar(150),
@CveTabla int,
@CveCampoLlave int,
@EsAdministrador bit',
@Orden = @OrdenRelacionMostrar,
@NombreTablaSQL = @NombreTablaSQLRelacionMostrar,
@NombreTabla = @NombreTablaRelacionMostrar,
@NombreCampoSQL = @NombreCampoSQLRelacionMostrar,
@NombreCampo = @NombreCampoRelacionMostrar,
@CveTabla = @CveTablaRelacionMostrar,
@CveCampoLlave = @CveCampoLlaveRelacionMostrar,
@EsAdministrador = @EsAdministrador;
FETCH NEXT FROM CursorRelacionesMostrar INTO
@OrdenRelacionMostrar,
@CveTablaRelacionMostrar,
@NombreTablaSQLRelacionMostrar,
@NombreTablaRelacionMostrar,
@CveCampoLlaveRelacionMostrar,
@NombreCampoLlaveRelacionMostrar,
@NombreCampoSQLRelacionMostrar,
@NombreCampoRelacionMostrar;
END;
CLOSE CursorRelacionesMostrar;
DEALLOCATE CursorRelacionesMostrar;
SELECT
RV.CveBitacora,
RV.Orden,
RV.NombreTablaSQL,
RV.NombreTabla,
RV.NombreCampoSQL,
RV.NombreCampo,
RV.ValorClave,
RV.ValorMostrar
FROM #RelacionesVisuales AS RV
INNER JOIN #BitacorasPagina AS P ON P.CveBitacora = RV.CveBitacora
ORDER BY
P.Orden,
RV.Orden;
SET @Return = 1;
END TRY
BEGIN CATCH
SET @ErrorMostrar = 'Ocurrió un error al consultar la bitácora; favor de contactar a Sistemas.';
SET @ErrorTipo = 1;
SET @Return = 0;
DECLARE @ErrorTecnico nvarchar(2048) = CONCAT(
'Número: ', ERROR_NUMBER(),
'; Procedimiento: ', COALESCE(
ERROR_PROCEDURE(),
'PA_Bit_BitacoraListByRelations'
),
'; Línea: ', ERROR_LINE(),
'; Detalle: ', ERROR_MESSAGE()
);
RAISERROR(N'%s', 10, 1, @ErrorTecnico);
END CATCH;
END;
GO
CREATE OR ALTER PROCEDURE dbo.PA_Bit_BitacoraResumenListByRelations
@RelacionesXml xml = NULL,
@RelacionesMostrarXml xml = NULL,
@RegistrosOmitidos int,
@RegistrosPorPagina int,
@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT
@ErrorMostrar = NULL,
@ErrorTipo = 0,
@Return = 0;
BEGIN TRY
IF @RegistrosOmitidos < 0 OR @RegistrosPorPagina <= 0
BEGIN
SET @ErrorMostrar = 'Los datos de paginación no son válidos.';
SET @ErrorTipo = 2;
RETURN;
END;
DECLARE @EsAdministrador bit = 0;
DECLARE @EsDesarrollador bit = 0;
SELECT
@EsAdministrador = CASE
WHEN R.NombreRol IN ('SuperUsuario', 'Administrador') THEN 1
ELSE 0
END,
@EsDesarrollador = CASE
WHEN R.NombreRol = 'Empresa' THEN 1
ELSE 0
END
FROM dbo.Sis_Usuarios AS U
INNER JOIN dbo.Sis_Roles AS R ON R.CveRol = U.CveRol
WHERE U.CveUsuario = @CveUsuarioEjecuta
AND U.Activo = 1
AND R.Activo = 1;
DECLARE @Filtros TABLE
(
Orden int NOT NULL PRIMARY KEY,
NombreTablaSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreCampoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
Valor nvarchar(250)
COLLATE Modern_Spanish_CS_AS NOT NULL,
SoloExistencia bit NOT NULL
);
IF @RelacionesXml IS NOT NULL
BEGIN
DECLARE @IdRelaciones int;
EXEC sys.sp_xml_preparedocument
@IdRelaciones OUTPUT,
@RelacionesXml;
INSERT INTO @Filtros
(
Orden,
NombreTablaSQL,
NombreCampoSQL,
Valor,
SoloExistencia
)
SELECT
Orden,
Tabla,
Campo,
Valor,
ISNULL(SoloExistencia, 0)
FROM OPENXML(
@IdRelaciones,
'/Relaciones/Relacion',
1
)
WITH
(
Orden int '@Orden',
Tabla varchar(128) '@Tabla',
Campo varchar(128) '@Campo',
Valor nvarchar(250) '@Valor',
SoloExistencia bit '@SoloExistencia'
);
EXEC sys.sp_xml_removedocument @IdRelaciones;
END;
DECLARE @FiltrosResueltos TABLE
(
Orden int NOT NULL PRIMARY KEY,
CveTabla int NOT NULL,
CveCampo int NOT NULL,
TipoDatoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
Valor nvarchar(250)
COLLATE Modern_Spanish_CS_AS NOT NULL,
SoloExistencia bit NOT NULL,
EsEntero bit NOT NULL
);
INSERT INTO @FiltrosResueltos
(
Orden,
CveTabla,
CveCampo,
TipoDatoSQL,
Valor,
SoloExistencia,
EsEntero
)
SELECT
F.Orden,
T.CveTabla,
C.CveCampo,
C.TipoDatoSQL,
F.Valor,
F.SoloExistencia,
CASE
WHEN C.TipoDatoSQL IN
(
'tinyint',
'smallint',
'int',
'bigint'
) THEN 1
ELSE 0
END
FROM @Filtros AS F
INNER JOIN dbo.Bit_Tablas AS T ON T.NombreTablaSQL = F.NombreTablaSQL
AND T.Activo = 1
INNER JOIN dbo.Bit_Campos AS C ON C.CveTabla = T.CveTabla
AND C.NombreCampoSQL = F.NombreCampoSQL
AND C.Activo = 1
INNER JOIN sys.schemas AS SF ON SF.name = 'dbo'
INNER JOIN sys.tables AS TF ON TF.schema_id = SF.schema_id
AND TF.name COLLATE Modern_Spanish_CS_AS = T.NombreTablaSQL
INNER JOIN sys.columns AS CF ON CF.object_id = TF.object_id
AND CF.name COLLATE Modern_Spanish_CS_AS = C.NombreCampoSQL
WHERE C.TipoDatoSQL IS NOT NULL;
IF (SELECT COUNT(1) FROM @Filtros) <>
(SELECT COUNT(1) FROM @FiltrosResueltos)
BEGIN
SET @ErrorMostrar = 'Una relación utiliza una tabla o campo que no está configurado en la bitácora.';
SET @ErrorTipo = 2;
RETURN;
END;
IF EXISTS
(
SELECT 1
FROM @FiltrosResueltos
WHERE SoloExistencia = 0
AND EsEntero = 1
AND TRY_CONVERT(bigint, Valor) IS NULL
)
BEGIN
SET @ErrorMostrar = 'El valor de una relación numérica no es válido.';
SET @ErrorTipo = 2;
RETURN;
END;
DECLARE @RelacionesMostrar TABLE
(
Orden int NOT NULL,
NombreTablaSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreCampoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL
);
IF @RelacionesMostrarXml IS NOT NULL
BEGIN
INSERT INTO @RelacionesMostrar
(
Orden,
NombreTablaSQL,
NombreCampoSQL
)
SELECT
R.value('@Orden', 'int'),
R.value('@Tabla', 'varchar(128)'),
R.value('@Campo', 'varchar(128)')
FROM @RelacionesMostrarXml.nodes('/RelacionesMostrar/Relacion') AS X(R);
END;
IF (SELECT COUNT(1) FROM @RelacionesMostrar) > 10
OR EXISTS
(
SELECT 1
FROM @RelacionesMostrar
WHERE Orden <= 0
)
OR EXISTS
(
SELECT Orden
FROM @RelacionesMostrar
GROUP BY Orden
HAVING COUNT(1) > 1
)
OR EXISTS
(
SELECT
NombreTablaSQL,
NombreCampoSQL
FROM @RelacionesMostrar
GROUP BY
NombreTablaSQL,
NombreCampoSQL
HAVING COUNT(1) > 1
)
BEGIN
SET @ErrorMostrar = 'La configuración de relaciones a mostrar no es válida.';
SET @ErrorTipo = 2;
RETURN;
END;
DECLARE @RelacionesMostrarResueltas TABLE
(
Orden int NOT NULL PRIMARY KEY,
CveTabla int NOT NULL,
NombreTablaSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreTabla varchar(150)
COLLATE Modern_Spanish_CS_AS NOT NULL,
CveCampoLlave int NOT NULL,
NombreCampoLlaveSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
CveCampoMostrar int NOT NULL,
NombreCampoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreCampo varchar(150)
COLLATE Modern_Spanish_CS_AS NOT NULL
);
INSERT INTO @RelacionesMostrarResueltas
(
Orden,
CveTabla,
NombreTablaSQL,
NombreTabla,
CveCampoLlave,
NombreCampoLlaveSQL,
CveCampoMostrar,
NombreCampoSQL,
NombreCampo
)
SELECT
R.Orden,
T.CveTabla,
T.NombreTablaSQL,
T.NombreMostrar,
CL.CveCampo,
CL.NombreCampoSQL,
CM.CveCampo,
CM.NombreCampoSQL,
CM.NombreMostrar
FROM @RelacionesMostrar AS R
INNER JOIN dbo.Bit_Tablas AS T ON T.NombreTablaSQL = R.NombreTablaSQL
AND T.Activo = 1
AND T.NombreCampoLlaveSQL IS NOT NULL
INNER JOIN dbo.Bit_Campos AS CL ON CL.CveTabla = T.CveTabla
AND CL.NombreCampoSQL = T.NombreCampoLlaveSQL
AND CL.Activo = 1
INNER JOIN dbo.Bit_Campos AS CM ON CM.CveTabla = T.CveTabla
AND CM.NombreCampoSQL = R.NombreCampoSQL
AND CM.MostrarEnBitacora = 1
AND CM.Activo = 1
INNER JOIN sys.schemas AS SC ON SC.name = 'dbo'
INNER JOIN sys.tables AS ST ON ST.schema_id = SC.schema_id
AND ST.name COLLATE Modern_Spanish_CS_AS = T.NombreTablaSQL
INNER JOIN sys.columns AS SCL ON SCL.object_id = ST.object_id
AND SCL.name COLLATE Modern_Spanish_CS_AS = CL.NombreCampoSQL
INNER JOIN sys.columns AS SCM ON SCM.object_id = ST.object_id
AND SCM.name COLLATE Modern_Spanish_CS_AS = CM.NombreCampoSQL;
IF (SELECT COUNT(1) FROM @RelacionesMostrar) <>
(SELECT COUNT(1) FROM @RelacionesMostrarResueltas)
BEGIN
SET @ErrorMostrar = 'Una relación a mostrar utiliza una tabla o campo no permitido.';
SET @ErrorTipo = 2;
RETURN;
END;
CREATE TABLE #BitacorasCoincidentes
(
CveBitacora bigint NOT NULL PRIMARY KEY,
FechaMovimiento datetime NOT NULL
);
INSERT INTO #BitacorasCoincidentes
(
CveBitacora,
FechaMovimiento
)
SELECT
B.CveBitacora,
B.FechaMovimiento
FROM (
SELECT R.CveBitacora, R.CveTabla, R.CveTipoMovimiento,
COALESCE(R.LlaveRegistroTexto, CONVERT(nvarchar(250), R.LlaveRegistro)) AS LlaveRegistro,
E.CveDefinicionAccion, E.CveUsuarioEjecuta, E.CveUsuarioAutoriza, E.FechaAutorizacion, E.FechaMovimiento, E.DireccionIP, E.NombreEquipo, E.Modulo,
CASE WHEN @EsAdministrador = 1 OR NOT EXISTS
(
SELECT 1
FROM dbo.Bit_Bitacora AS R2
WHERE R2.CveBitacoraEvento = E.CveBitacoraEvento
AND NOT ((
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BRCliente
INNER JOIN dbo.Bit_Tablas AS TCliente ON TCliente.CveTabla =
BRCliente.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS CCliente ON CCliente.CveCampo =
BRCliente.CveCampoRelacion
AND CCliente.CveTabla = TCliente.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente =
BRCliente.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BRCliente.CveBitacora = R2.CveBitacora
AND BRCliente.VisibleDesarrollador = 1
AND TCliente.NombreTablaSQL = 'Clientes'
AND CCliente.NombreCampoSQL = 'CveCliente'
)
)
))
) THEN E.DescripcionMovimiento
ELSE N'Operación con registros de acceso restringido.' END AS DescripcionMovimiento
FROM dbo.Bit_Bitacora AS R
INNER JOIN dbo.Bit_BitacoraEventos AS E ON E.CveBitacoraEvento = R.CveBitacoraEvento
) AS B
WHERE
(
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BRCliente
INNER JOIN dbo.Bit_Tablas AS TCliente ON TCliente.CveTabla =
BRCliente.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS CCliente ON CCliente.CveCampo =
BRCliente.CveCampoRelacion
AND CCliente.CveTabla = TCliente.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente =
BRCliente.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BRCliente.CveBitacora = B.CveBitacora
AND BRCliente.VisibleDesarrollador = 1
AND TCliente.NombreTablaSQL = 'Clientes'
AND CCliente.NombreCampoSQL = 'CveCliente'
)
)
)
AND
(
@EsDesarrollador = 0
OR NOT EXISTS
(
SELECT 1
FROM @FiltrosResueltos AS FCliente
INNER JOIN dbo.Bit_Tablas AS TClienteFiltro ON TClienteFiltro.CveTabla = FCliente.CveTabla
INNER JOIN dbo.Bit_Campos AS CClienteFiltro ON CClienteFiltro.CveCampo = FCliente.CveCampo
AND CClienteFiltro.CveTabla =
TClienteFiltro.CveTabla
WHERE TClienteFiltro.NombreTablaSQL = 'Clientes'
AND CClienteFiltro.NombreCampoSQL = 'CveCliente'
AND FCliente.SoloExistencia = 0
AND NOT EXISTS
(
SELECT 1
FROM dbo.Sis_UsuariosClientes AS UCClienteFiltro
WHERE UCClienteFiltro.CveUsuario =
@CveUsuarioEjecuta
AND UCClienteFiltro.CveCliente =
TRY_CONVERT(bigint, FCliente.Valor)
AND UCClienteFiltro.Activo = 1
)
)
)
AND NOT EXISTS
(
SELECT 1
FROM @FiltrosResueltos AS F
WHERE NOT EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BR
WHERE BR.CveBitacora = B.CveBitacora
AND BR.CveTablaRelacionada = F.CveTabla
AND BR.CveCampoRelacion = F.CveCampo
AND
(
@EsAdministrador = 1
OR BR.VisibleDesarrollador = 1
)
AND
(
F.SoloExistencia = 1
OR
(
(
F.EsEntero = 1
AND BR.ValorRelacionNumero =
TRY_CONVERT(bigint, F.Valor)
)
OR
(
F.EsEntero = 0
AND BR.ValorRelacionTexto =
F.Valor COLLATE Modern_Spanish_CS_AS
)
)
)
)
);
DECLARE @TotalRegistros int;
SELECT @TotalRegistros = COUNT(DISTINCT CveBitacora)
FROM #BitacorasCoincidentes;
CREATE TABLE #BitacorasPagina
(
CveBitacora bigint NOT NULL PRIMARY KEY,
Orden int NOT NULL
);
INSERT INTO #BitacorasPagina
(
CveBitacora,
Orden
)
SELECT
C.CveBitacora,
ROW_NUMBER() OVER
(
ORDER BY
C.FechaMovimiento DESC,
C.CveBitacora DESC
)
FROM #BitacorasCoincidentes AS C
ORDER BY
C.FechaMovimiento DESC,
C.CveBitacora DESC
OFFSET @RegistrosOmitidos ROWS
FETCH NEXT @RegistrosPorPagina ROWS ONLY;
SELECT @TotalRegistros AS TotalRegistros;
SELECT
B.CveBitacora,
B.CveTabla,
T.NombreTablaSQL,
T.NombreMostrar AS NombreTabla,
B.CveTipoMovimiento,
M.Nombre AS TipoMovimiento,
B.CveDefinicionAccion,
A.NombreAccion,
A.DescripcionAccion,
B.CveUsuarioEjecuta,
COALESCE(
NULLIF(U.NombreUsuario, ''),
CONCAT('(', B.CveUsuarioEjecuta, ') Eliminado')
) AS NombreUsuarioEjecuta,
B.CveUsuarioAutoriza,
B.FechaAutorizacion,
B.LlaveRegistro,
B.DescripcionMovimiento,
B.FechaMovimiento,
B.DireccionIP,
B.NombreEquipo,
B.Modulo
FROM #BitacorasPagina AS P
INNER JOIN (
SELECT R.CveBitacora, R.CveTabla, R.CveTipoMovimiento,
COALESCE(R.LlaveRegistroTexto, CONVERT(nvarchar(250), R.LlaveRegistro)) AS LlaveRegistro,
E.CveDefinicionAccion, E.CveUsuarioEjecuta, E.CveUsuarioAutoriza, E.FechaAutorizacion, E.FechaMovimiento, E.DireccionIP, E.NombreEquipo, E.Modulo,
CASE WHEN @EsAdministrador = 1 OR NOT EXISTS
(
SELECT 1
FROM dbo.Bit_Bitacora AS R2
WHERE R2.CveBitacoraEvento = E.CveBitacoraEvento
AND NOT ((
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BRCliente
INNER JOIN dbo.Bit_Tablas AS TCliente ON TCliente.CveTabla =
BRCliente.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS CCliente ON CCliente.CveCampo =
BRCliente.CveCampoRelacion
AND CCliente.CveTabla = TCliente.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente =
BRCliente.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BRCliente.CveBitacora = R2.CveBitacora
AND BRCliente.VisibleDesarrollador = 1
AND TCliente.NombreTablaSQL = 'Clientes'
AND CCliente.NombreCampoSQL = 'CveCliente'
)
)
))
) THEN E.DescripcionMovimiento
ELSE N'Operación con registros de acceso restringido.' END AS DescripcionMovimiento
FROM dbo.Bit_Bitacora AS R
INNER JOIN dbo.Bit_BitacoraEventos AS E ON E.CveBitacoraEvento = R.CveBitacoraEvento
) AS B
ON B.CveBitacora = P.CveBitacora
INNER JOIN dbo.Bit_Tablas AS T ON T.CveTabla = B.CveTabla
INNER JOIN dbo.Bit_TiposMovimiento AS M ON M.CveTipoMovimiento = B.CveTipoMovimiento
LEFT JOIN dbo.Bit_DefinicionesAccion AS A ON A.CveDefinicionAccion = B.CveDefinicionAccion
LEFT JOIN dbo.Sis_Usuarios AS U ON U.CveUsuario = B.CveUsuarioEjecuta
ORDER BY P.Orden;
CREATE TABLE #RelacionesVisuales
(
CveBitacora bigint NOT NULL,
Orden int NOT NULL,
NombreTablaSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreTabla varchar(150)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreCampoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreCampo varchar(150)
COLLATE Modern_Spanish_CS_AS NOT NULL,
ValorClave nvarchar(250)
COLLATE Modern_Spanish_CS_AS NOT NULL,
ValorMostrar nvarchar(max)
COLLATE Modern_Spanish_CS_AS NOT NULL
);
DECLARE @OrdenRelacionMostrar int;
DECLARE @CveTablaRelacionMostrar int;
DECLARE @NombreTablaSQLRelacionMostrar varchar(128);
DECLARE @NombreTablaRelacionMostrar varchar(150);
DECLARE @CveCampoLlaveRelacionMostrar int;
DECLARE @NombreCampoLlaveRelacionMostrar varchar(128);
DECLARE @NombreCampoSQLRelacionMostrar varchar(128);
DECLARE @NombreCampoRelacionMostrar varchar(150);
DECLARE @SqlRelacionMostrar nvarchar(max);
-- Tabla, llave y campo visible ya fueron resueltos contra la allowlist
-- de Bit_Tablas/Bit_Campos y se delimitan nuevamente con QUOTENAME.
DECLARE CursorRelacionesMostrar CURSOR LOCAL FAST_FORWARD FOR
SELECT
Orden,
CveTabla,
NombreTablaSQL,
NombreTabla,
CveCampoLlave,
NombreCampoLlaveSQL,
NombreCampoSQL,
NombreCampo
FROM @RelacionesMostrarResueltas
ORDER BY Orden;
OPEN CursorRelacionesMostrar;
FETCH NEXT FROM CursorRelacionesMostrar INTO
@OrdenRelacionMostrar,
@CveTablaRelacionMostrar,
@NombreTablaSQLRelacionMostrar,
@NombreTablaRelacionMostrar,
@CveCampoLlaveRelacionMostrar,
@NombreCampoLlaveRelacionMostrar,
@NombreCampoSQLRelacionMostrar,
@NombreCampoRelacionMostrar;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SqlRelacionMostrar = N'
INSERT INTO #RelacionesVisuales
(
CveBitacora,
Orden,
NombreTablaSQL,
NombreTabla,
NombreCampoSQL,
NombreCampo,
ValorClave,
ValorMostrar
)
SELECT
BR.CveBitacora,
@Orden,
@NombreTablaSQL,
@NombreTabla,
@NombreCampoSQL,
@NombreCampo,
BR.LlaveRegistroRelacionada,
CASE
WHEN V.' + QUOTENAME(@NombreCampoLlaveRelacionMostrar) + N' IS NULL
THEN CONCAT(N''('', BR.LlaveRegistroRelacionada, N'') Eliminada'')
WHEN NULLIF(CONVERT(nvarchar(max), V.' + QUOTENAME(@NombreCampoSQLRelacionMostrar) + N'), N'''') IS NULL
THEN CONCAT(N''('', BR.LlaveRegistroRelacionada, N'')'')
ELSE CONVERT(nvarchar(max), V.' + QUOTENAME(@NombreCampoSQLRelacionMostrar) + N')
END
FROM #BitacorasPagina AS P
INNER JOIN dbo.Bit_BitacoraRelaciones AS BR ON BR.CveBitacora = P.CveBitacora
INNER JOIN dbo.Bit_Bitacora AS B
ON B.CveBitacora = P.CveBitacora
LEFT JOIN dbo.' + QUOTENAME(@NombreTablaSQLRelacionMostrar) + N' AS V ON CONVERT(nvarchar(250), V.' + QUOTENAME(@NombreCampoLlaveRelacionMostrar) + N')
COLLATE Modern_Spanish_CS_AS =
BR.LlaveRegistroRelacionada COLLATE Modern_Spanish_CS_AS
WHERE BR.CveTablaRelacionada = @CveTabla
AND BR.CveCampoRelacion = @CveCampoLlave
AND NOT
(
BR.CveTipoRelacion = 1
AND BR.CveTablaRelacionada = B.CveTabla
)
AND
(
@EsAdministrador = 1
OR BR.VisibleDesarrollador = 1
);';
EXEC sys.sp_executesql
@SqlRelacionMostrar,
N'@Orden int,
@NombreTablaSQL varchar(128),
@NombreTabla varchar(150),
@NombreCampoSQL varchar(128),
@NombreCampo varchar(150),
@CveTabla int,
@CveCampoLlave int,
@EsAdministrador bit',
@Orden = @OrdenRelacionMostrar,
@NombreTablaSQL = @NombreTablaSQLRelacionMostrar,
@NombreTabla = @NombreTablaRelacionMostrar,
@NombreCampoSQL = @NombreCampoSQLRelacionMostrar,
@NombreCampo = @NombreCampoRelacionMostrar,
@CveTabla = @CveTablaRelacionMostrar,
@CveCampoLlave = @CveCampoLlaveRelacionMostrar,
@EsAdministrador = @EsAdministrador;
FETCH NEXT FROM CursorRelacionesMostrar INTO
@OrdenRelacionMostrar,
@CveTablaRelacionMostrar,
@NombreTablaSQLRelacionMostrar,
@NombreTablaRelacionMostrar,
@CveCampoLlaveRelacionMostrar,
@NombreCampoLlaveRelacionMostrar,
@NombreCampoSQLRelacionMostrar,
@NombreCampoRelacionMostrar;
END;
CLOSE CursorRelacionesMostrar;
DEALLOCATE CursorRelacionesMostrar;
SELECT
RV.CveBitacora,
RV.Orden,
RV.NombreTablaSQL,
RV.NombreTabla,
RV.NombreCampoSQL,
RV.NombreCampo,
RV.ValorClave,
RV.ValorMostrar
FROM #RelacionesVisuales AS RV
INNER JOIN #BitacorasPagina AS P ON P.CveBitacora = RV.CveBitacora
ORDER BY
P.Orden,
RV.Orden;
SET @Return = 1;
END TRY
BEGIN CATCH
SET @ErrorMostrar = 'Ocurrió un error al consultar la bitácora; favor de contactar a Sistemas.';
SET @ErrorTipo = 1;
SET @Return = 0;
DECLARE @ErrorTecnico nvarchar(2048) = CONCAT(
'Número: ', ERROR_NUMBER(),
'; Procedimiento: ', COALESCE(
ERROR_PROCEDURE(),
'PA_Bit_BitacoraListByRelations'
),
'; Línea: ', ERROR_LINE(),
'; Detalle: ', ERROR_MESSAGE()
);
RAISERROR(N'%s', 10, 1, @ErrorTecnico);
END CATCH;
END;
GO
CREATE OR ALTER PROCEDURE dbo.PA_Bit_BitacoraDetalleGet
@CveBitacora bigint,
@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT
@ErrorMostrar = NULL,
@ErrorTipo = 0,
@Return = 0;
BEGIN TRY
IF @CveBitacora <= 0
BEGIN
SET @ErrorMostrar =
'La clave del movimiento de bitácora no es válida.';
SET @ErrorTipo = 2;
RETURN;
END;
DECLARE @EsAdministrador bit = 0;
DECLARE @EsDesarrollador bit = 0;
SELECT
@EsAdministrador = CASE
WHEN R.NombreRol IN
(
'SuperUsuario',
'Administrador'
) THEN 1
ELSE 0
END,
@EsDesarrollador = CASE
WHEN R.NombreRol = 'Empresa' THEN 1
ELSE 0
END
FROM dbo.Sis_Usuarios AS U
INNER JOIN dbo.Sis_Roles AS R ON R.CveRol = U.CveRol
WHERE U.CveUsuario = @CveUsuarioEjecuta
AND U.Activo = 1
AND R.Activo = 1;
IF NOT EXISTS
(
SELECT 1
FROM (
SELECT R.CveBitacora, R.CveTabla, R.CveTipoMovimiento,
COALESCE(R.LlaveRegistroTexto, CONVERT(nvarchar(250), R.LlaveRegistro)) AS LlaveRegistro,
E.CveDefinicionAccion, E.CveUsuarioEjecuta, E.CveUsuarioAutoriza, E.FechaAutorizacion, E.FechaMovimiento, E.DireccionIP, E.NombreEquipo, E.Modulo,
CASE WHEN @EsAdministrador = 1 OR NOT EXISTS
(
SELECT 1
FROM dbo.Bit_Bitacora AS R2
WHERE R2.CveBitacoraEvento = E.CveBitacoraEvento
AND NOT ((
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BRCliente
INNER JOIN dbo.Bit_Tablas AS TCliente ON TCliente.CveTabla =
BRCliente.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS CCliente ON CCliente.CveCampo =
BRCliente.CveCampoRelacion
AND CCliente.CveTabla = TCliente.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente =
BRCliente.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BRCliente.CveBitacora = R2.CveBitacora
AND BRCliente.VisibleDesarrollador = 1
AND TCliente.NombreTablaSQL = 'Clientes'
AND CCliente.NombreCampoSQL = 'CveCliente'
)
)
))
) THEN E.DescripcionMovimiento
ELSE N'Operación con registros de acceso restringido.' END AS DescripcionMovimiento
FROM dbo.Bit_Bitacora AS R
INNER JOIN dbo.Bit_BitacoraEventos AS E ON E.CveBitacoraEvento = R.CveBitacoraEvento
) AS B
WHERE B.CveBitacora = @CveBitacora
AND
(
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BRCliente
INNER JOIN dbo.Bit_Tablas AS TCliente ON TCliente.CveTabla =
BRCliente.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS CCliente ON CCliente.CveCampo =
BRCliente.CveCampoRelacion
AND CCliente.CveTabla = TCliente.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente =
BRCliente.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BRCliente.CveBitacora = B.CveBitacora
AND BRCliente.VisibleDesarrollador = 1
AND TCliente.NombreTablaSQL = 'Clientes'
AND CCliente.NombreCampoSQL = 'CveCliente'
)
)
)
)
BEGIN
SET @ErrorMostrar =
'No se encontró el movimiento de bitácora solicitado.';
SET @ErrorTipo = 2;
RETURN;
END;
SELECT
B.CveBitacora,
B.CveTabla,
T.NombreTablaSQL,
T.NombreMostrar AS NombreTabla,
B.CveTipoMovimiento,
M.Nombre AS TipoMovimiento,
B.CveDefinicionAccion,
A.NombreAccion,
A.DescripcionAccion,
B.CveUsuarioEjecuta,
COALESCE(
NULLIF(U.NombreUsuario, ''),
CONCAT('(', B.CveUsuarioEjecuta, ') Eliminado')
) AS NombreUsuarioEjecuta,
B.CveUsuarioAutoriza,
B.FechaAutorizacion,
B.LlaveRegistro,
B.DescripcionMovimiento,
B.FechaMovimiento,
B.DireccionIP,
B.NombreEquipo,
B.Modulo
FROM (
SELECT R.CveBitacora, R.CveTabla, R.CveTipoMovimiento,
COALESCE(R.LlaveRegistroTexto, CONVERT(nvarchar(250), R.LlaveRegistro)) AS LlaveRegistro,
E.CveDefinicionAccion, E.CveUsuarioEjecuta, E.CveUsuarioAutoriza, E.FechaAutorizacion, E.FechaMovimiento, E.DireccionIP, E.NombreEquipo, E.Modulo,
CASE WHEN @EsAdministrador = 1 OR NOT EXISTS
(
SELECT 1
FROM dbo.Bit_Bitacora AS R2
WHERE R2.CveBitacoraEvento = E.CveBitacoraEvento
AND NOT ((
@EsAdministrador = 1
OR
(
@EsDesarrollador = 1
AND EXISTS
(
SELECT 1
FROM dbo.Bit_BitacoraRelaciones AS BRCliente
INNER JOIN dbo.Bit_Tablas AS TCliente ON TCliente.CveTabla =
BRCliente.CveTablaRelacionada
INNER JOIN dbo.Bit_Campos AS CCliente ON CCliente.CveCampo =
BRCliente.CveCampoRelacion
AND CCliente.CveTabla = TCliente.CveTabla
INNER JOIN dbo.Sis_UsuariosClientes AS UC ON UC.CveCliente =
BRCliente.ValorRelacionNumero
AND UC.CveUsuario = @CveUsuarioEjecuta
AND UC.Activo = 1
WHERE BRCliente.CveBitacora = R2.CveBitacora
AND BRCliente.VisibleDesarrollador = 1
AND TCliente.NombreTablaSQL = 'Clientes'
AND CCliente.NombreCampoSQL = 'CveCliente'
)
)
))
) THEN E.DescripcionMovimiento
ELSE N'Operación con registros de acceso restringido.' END AS DescripcionMovimiento
FROM dbo.Bit_Bitacora AS R
INNER JOIN dbo.Bit_BitacoraEventos AS E ON E.CveBitacoraEvento = R.CveBitacoraEvento
) AS B
INNER JOIN dbo.Bit_Tablas AS T ON T.CveTabla = B.CveTabla
INNER JOIN dbo.Bit_TiposMovimiento AS M ON M.CveTipoMovimiento = B.CveTipoMovimiento
LEFT JOIN dbo.Bit_DefinicionesAccion AS A ON A.CveDefinicionAccion = B.CveDefinicionAccion
LEFT JOIN dbo.Sis_Usuarios AS U ON U.CveUsuario = B.CveUsuarioEjecuta
WHERE B.CveBitacora = @CveBitacora;
CREATE TABLE #RegistrosAutorizados (CveBitacora bigint NOT NULL PRIMARY KEY);
INSERT INTO #RegistrosAutorizados VALUES (@CveBitacora);
CREATE TABLE #CamposDetalle
(
CveBitacoraCampo bigint NOT NULL PRIMARY KEY,
CveBitacora bigint NOT NULL,
CveCampo int NOT NULL,
NombreCampoSQL varchar(128)
COLLATE Modern_Spanish_CS_AS NOT NULL,
NombreMostrar varchar(150)
COLLATE Modern_Spanish_CS_AS NOT NULL,
ValorAnterior nvarchar(max)
COLLATE Modern_Spanish_CS_AS NULL,
ValorNuevo nvarchar(max)
COLLATE Modern_Spanish_CS_AS NULL,
ValorAnteriorMostrar nvarchar(max)
COLLATE Modern_Spanish_CS_AS NULL,
ValorNuevoMostrar nvarchar(max)
COLLATE Modern_Spanish_CS_AS NULL
);
INSERT INTO #CamposDetalle
(
CveBitacoraCampo,
CveBitacora,
CveCampo,
NombreCampoSQL,
NombreMostrar,
ValorAnterior,
ValorNuevo,
ValorAnteriorMostrar,
ValorNuevoMostrar
)
SELECT
BC.CveBitacoraCampo,
BC.CveBitacora,
BC.CveCampo,
C.NombreCampoSQL,
C.NombreMostrar,
BC.ValorAnterior,
BC.ValorNuevo,
BC.ValorAnteriorMostrar,
BC.ValorNuevoMostrar
FROM dbo.Bit_BitacoraCampos AS BC
INNER JOIN dbo.Bit_Campos AS C ON C.CveCampo = BC.CveCampo
WHERE EXISTS (SELECT 1 FROM #RegistrosAutorizados AS V WHERE V.CveBitacora = BC.CveBitacora)
AND
(
@EsAdministrador = 1
OR C.MostrarEnBitacora = 1
);
DECLARE @CveCampoOrigenReferencia int;
DECLARE @NombreTablaReferencia varchar(128);
DECLARE @NombreCampoLlaveReferencia varchar(128);
DECLARE @NombreCampoMostrarReferencia varchar(128);
DECLARE @SqlCampoReferencia nvarchar(max);
DECLARE CursorCamposReferencia CURSOR LOCAL FAST_FORWARD FOR
SELECT DISTINCT
CO.CveCampo,
TR.NombreTablaSQL,
CL.NombreCampoSQL,
CM.NombreCampoSQL
FROM #CamposDetalle AS CD
INNER JOIN dbo.Bit_Campos AS CO ON CO.CveCampo = CD.CveCampo
AND CO.Activo = 1
INNER JOIN dbo.Bit_Tablas AS TR ON TR.CveTabla = CO.CveTablaReferencia
AND TR.Activo = 1
AND TR.NombreCampoLlaveSQL IS NOT NULL
INNER JOIN dbo.Bit_Campos AS CL ON CL.CveTabla = TR.CveTabla
AND CL.NombreCampoSQL = TR.NombreCampoLlaveSQL
AND CL.Activo = 1
INNER JOIN dbo.Bit_Campos AS CM ON CM.CveCampo = CO.CveCampoMostrarReferencia
AND CM.CveTabla = TR.CveTabla
AND CM.MostrarEnBitacora = 1
AND CM.Activo = 1
INNER JOIN sys.schemas AS SC ON SC.name = 'dbo'
INNER JOIN sys.tables AS ST ON ST.schema_id = SC.schema_id
AND ST.name COLLATE Modern_Spanish_CS_AS = TR.NombreTablaSQL
INNER JOIN sys.columns AS SCL ON SCL.object_id = ST.object_id
AND SCL.name COLLATE Modern_Spanish_CS_AS =
CL.NombreCampoSQL
INNER JOIN sys.columns AS SCM ON SCM.object_id = ST.object_id
AND SCM.name COLLATE Modern_Spanish_CS_AS =
CM.NombreCampoSQL;
OPEN CursorCamposReferencia;
FETCH NEXT FROM CursorCamposReferencia INTO
@CveCampoOrigenReferencia,
@NombreTablaReferencia,
@NombreCampoLlaveReferencia,
@NombreCampoMostrarReferencia;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SqlCampoReferencia = N'
UPDATE CD
SET
CD.ValorAnteriorMostrar = CASE
WHEN CD.ValorAnteriorMostrar IS NOT NULL THEN CD.ValorAnteriorMostrar
WHEN CD.ValorAnterior IS NULL THEN NULL
WHEN VA.' + QUOTENAME(@NombreCampoLlaveReferencia) + N' IS NULL
THEN CONCAT(N''('', CD.ValorAnterior, N'') Eliminada'')
WHEN NULLIF(CONVERT(nvarchar(max), VA.' + QUOTENAME(@NombreCampoMostrarReferencia) + N'), N'''') IS NULL
THEN CONCAT(N''('', CD.ValorAnterior, N'')'')
ELSE CONCAT(CONVERT(nvarchar(max), VA.' + QUOTENAME(@NombreCampoMostrarReferencia) + N'), N'' (catálogo actual)'')
END,
CD.ValorNuevoMostrar = CASE
WHEN CD.ValorNuevoMostrar IS NOT NULL THEN CD.ValorNuevoMostrar
WHEN CD.ValorNuevo IS NULL THEN NULL
WHEN VN.' + QUOTENAME(@NombreCampoLlaveReferencia) + N' IS NULL
THEN CONCAT(N''('', CD.ValorNuevo, N'') Eliminada'')
WHEN NULLIF(CONVERT(nvarchar(max), VN.' + QUOTENAME(@NombreCampoMostrarReferencia) + N'), N'''') IS NULL
THEN CONCAT(N''('', CD.ValorNuevo, N'')'')
ELSE CONCAT(CONVERT(nvarchar(max), VN.' + QUOTENAME(@NombreCampoMostrarReferencia) + N'), N'' (catálogo actual)'')
END
FROM #CamposDetalle AS CD
LEFT JOIN dbo.' + QUOTENAME(@NombreTablaReferencia) + N' AS VA ON CONVERT(nvarchar(250), VA.' + QUOTENAME(@NombreCampoLlaveReferencia) + N')
COLLATE Modern_Spanish_CS_AS =
CD.ValorAnterior COLLATE Modern_Spanish_CS_AS
LEFT JOIN dbo.' + QUOTENAME(@NombreTablaReferencia) + N' AS VN ON CONVERT(nvarchar(250), VN.' + QUOTENAME(@NombreCampoLlaveReferencia) + N')
COLLATE Modern_Spanish_CS_AS =
CD.ValorNuevo COLLATE Modern_Spanish_CS_AS
WHERE CD.CveCampo = @CveCampoOrigen;';
EXEC sys.sp_executesql
@SqlCampoReferencia,
N'@CveCampoOrigen int',
@CveCampoOrigen = @CveCampoOrigenReferencia;
FETCH NEXT FROM CursorCamposReferencia INTO
@CveCampoOrigenReferencia,
@NombreTablaReferencia,
@NombreCampoLlaveReferencia,
@NombreCampoMostrarReferencia;
END;
CLOSE CursorCamposReferencia;
DEALLOCATE CursorCamposReferencia;
UPDATE D
SET ValorAnteriorMostrar = COALESCE(D.ValorAnteriorMostrar, CASE D.ValorAnterior
WHEN N'1' THEN N'Lunes'
WHEN N'2' THEN N'Martes'
WHEN N'3' THEN N'Miércoles'
WHEN N'4' THEN N'Jueves'
WHEN N'5' THEN N'Viernes'
WHEN N'6' THEN N'Sábado'
WHEN N'7' THEN N'Domingo'
ELSE D.ValorAnterior END),
ValorNuevoMostrar = COALESCE(D.ValorNuevoMostrar, CASE D.ValorNuevo
WHEN N'1' THEN N'Lunes'
WHEN N'2' THEN N'Martes'
WHEN N'3' THEN N'Miércoles'
WHEN N'4' THEN N'Jueves'
WHEN N'5' THEN N'Viernes'
WHEN N'6' THEN N'Sábado'
WHEN N'7' THEN N'Domingo'
ELSE D.ValorNuevo END)
FROM #CamposDetalle AS D
INNER JOIN dbo.Bit_Campos AS C ON C.CveCampo = D.CveCampo
INNER JOIN dbo.Bit_Tablas AS T ON T.CveTabla = C.CveTabla
WHERE T.NombreTablaSQL = 'Sis_TurnosHorarios' AND C.NombreCampoSQL = 'DiaSemana';
SELECT
CveBitacoraCampo,
CveBitacora,
CveCampo,
NombreCampoSQL,
NombreMostrar,
ValorAnterior,
ValorNuevo,
COALESCE(ValorAnteriorMostrar, ValorAnterior) AS ValorAnteriorMostrar,
COALESCE(ValorNuevoMostrar, ValorNuevo) AS ValorNuevoMostrar
FROM #CamposDetalle
ORDER BY CveBitacoraCampo;
SET @Return = 1;
END TRY
BEGIN CATCH
SET @ErrorMostrar =
'Ocurrió un error al consultar el detalle de la bitácora; favor de contactar a Sistemas.';
SET @ErrorTipo = 1;
SET @Return = 0;
DECLARE @ErrorTecnico nvarchar(2048) = CONCAT(
'Número: ', ERROR_NUMBER(),
'; Procedimiento: ', COALESCE(
ERROR_PROCEDURE(),
'PA_Bit_BitacoraDetalleGet'
),
'; Línea: ', ERROR_LINE(),
'; Detalle: ', ERROR_MESSAGE()
);
RAISERROR(N'%s', 10, 1, @ErrorTecnico);
END CATCH;
END;
GO