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

1267 lines
51 KiB
Transact-SQL

/*
Simplificación de bitácora aprobada: una tabla de detalle y plantillas en Bit_Campos.
Instalado el 20/09/2026 en SIG_PlataformaDesarolladores con autorización del usuario.
Este archivo incluye sólo los dos PA modificados.
Requiere la migración de eventos ya instalada.
Instalación: respaldo verificado y una transacción externa en una conexión.
Ante cualquier error, el instalador debe detenerse y revertir la transacción completa.
No se reescribe ni elimina la bitácora histórica.
*/
SET NOCOUNT ON;
IF @@TRANCOUNT = 0
THROW 51000, 'El ajuste requiere una transacción externa del instalador.', 1;
IF DB_NAME() <> N'SIG_PlataformaDesarolladores'
THROW 51000, 'La base no coincide con la revisada para este ajuste.', 1;
IF OBJECT_ID(N'dbo.Bit_BitacoraEventos', N'U') IS NULL
OR COL_LENGTH('dbo.Bit_BitacoraCampos', 'ValorAnteriorMostrar') IS NULL
THROW 51000, 'Instale primero la estructura de eventos de bitácora.', 1;
IF COL_LENGTH('dbo.Bit_Campos', 'Plantilla') IS NULL
ALTER TABLE dbo.Bit_Campos ADD Plantilla nvarchar(1000) COLLATE Modern_Spanish_CS_AS NULL;
GO
IF @@TRANCOUNT = 0
THROW 51000, 'El ajuste requiere una transacción externa.', 1;
DECLARE @TablaHorarios int;
DECLARE @TablaTurnos int;
DECLARE @CampoNombreTurno int;
SELECT @TablaHorarios = CveTabla FROM dbo.Bit_Tablas WHERE NombreTablaSQL = 'Sis_TurnosHorarios';
SELECT @TablaTurnos = CveTabla FROM dbo.Bit_Tablas WHERE NombreTablaSQL = 'Sis_Turnos';
SELECT @CampoNombreTurno = CveCampo FROM dbo.Bit_Campos
WHERE CveTabla = @TablaTurnos AND NombreCampoSQL = 'Turno';
IF @TablaHorarios IS NULL OR @TablaTurnos IS NULL OR @CampoNombreTurno IS NULL
THROW 51000, 'No se encontró la configuración de turnos revisada.', 1;
IF
(
SELECT COUNT(*) FROM dbo.Bit_Campos
WHERE CveTabla = @TablaHorarios
AND NombreCampoSQL IN ('CveTurno', 'DiaSemana', 'HoraInicio', 'HoraFin')
) <> 4
THROW 51000, 'Faltan campos de los horarios en la configuración de bitácora.', 1;
-- Las fuentes permanecen activas para referencias y tokens, pero no se guardan individualmente.
UPDATE dbo.Bit_Campos
SET MostrarEnBitacora = 0, FechaMod = GETDATE()
WHERE CveTabla = @TablaHorarios
AND NombreCampoSQL IN ('CveTurno', 'DiaSemana', 'HoraInicio', 'HoraFin');
UPDATE dbo.Bit_Campos
SET CveTablaReferencia = @TablaTurnos,
CveCampoMostrarReferencia = @CampoNombreTurno,
FechaMod = GETDATE()
WHERE CveTabla = @TablaHorarios AND NombreCampoSQL = 'CveTurno';
IF EXISTS
(
SELECT 1 FROM dbo.Bit_Campos
WHERE CveTabla = @TablaHorarios AND NombreCampoSQL = 'Horario' AND Plantilla IS NULL
)
THROW 51000, 'Ya existe un campo Horario sin plantilla; revise la configuración antes de continuar.', 1;
IF NOT EXISTS
(
SELECT 1 FROM dbo.Bit_Campos
WHERE CveTabla = @TablaHorarios AND NombreCampoSQL = 'Horario'
)
BEGIN
INSERT INTO dbo.Bit_Campos
(
CveTabla, NombreCampoSQL, NombreMostrar, TipoDatoSQL,
MostrarEnBitacora, Activo, FechaAlta, Plantilla
)
VALUES
(
@TablaHorarios, 'Horario', 'Horario', 'nvarchar',
1, 1, GETDATE(), N'{Turno} {DiaSemana} {HoraInicio} - {HoraFin}'
);
END;
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_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