1267 lines
51 KiB
Transact-SQL
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
|