-- SP_Webhook_CaptureEvent — SQL Server / T-SQL -- -- Toda la lógica de captura del emulador vive acá, en un procedimiento -- propio y con nombre descriptivo — no directamente en el cuerpo de -- SBO_SP_PostTransactionNotice (ver mssql.sql), que es un hook compartido -- de SAP donde puede convivir código de otros add-ons. Así el nuestro -- queda identificable y fácil de mantener o remover por separado. -- -- Requiere que la UserTable "@OEVN" ya exista (creada por -- `npm run provision`, ver src/provisioning/). -- -- U_UserID: no se completa. SUSER_SNAME() da el login de la conexión a SQL -- Server (una cuenta técnica), no el usuario real de SAP que hizo la -- transacción — confirmado equivalente en HANA (CURRENT_USER, ver -- sp-webhook-capture-event-hana.sql). Ninguno de los 5 parámetros que -- recibe el hook trae ese dato, así que por ahora el campo queda sin -- poblar en las dos variantes. -- -- Name: en una UserTable de SAP, "Name" también debe ser único (no solo -- "Code") — confirmado contra Service Layer real (ODBC -2035 al repetir -- un Name, con Code distinto). Por eso Name usa el mismo UUID que Code: -- cualquier otro valor (como el propio ObjectType) se repite entre -- eventos del mismo tipo y hace fallar el INSERT en el segundo evento -- (en silencio, por el TRY/CATCH). -- -- Eco de nuestras propias escrituras: cualquier POST/PATCH/DELETE que -- hace el dispatcher sobre @OEVC/@EVC1/@OEVN/@EVN1 vía Service Layer -- dispara este mismo hook de nuevo, con un ObjectType especial de SAP -- para "operación genérica sobre una UserTable simple": un código -- negativo + tab + nombre físico de la tabla (confirmado real: -- "-3\t@OEVN" para un DELETE). Si insertáramos esa fila iba a generar -- otro eco al borrarla, indefinidamente — por eso NO se inserta nada -- cuando el ObjectType matchea ese patrón para una de nuestras 4 tablas -- (ver docs/DISENO.md, hallazgo 5). -- -- Filtro por suscripción activa: además de lo anterior, solo se inserta -- si existe al menos una fila en @EVC1 (con su @OEVC en State='A') para -- este ObjectType+TransType exacto. No es "lógica de negocio propia" del -- SP — consulta la misma tabla de configuración que ya es la fuente de -- verdad para el dispatcher, no una copia/lista fija a mantener -- sincronizada. Evita ensuciar @OEVN con todo lo que SAP genera y a -- nadie le interesa (en el ambiente de prueba, cientos de eventos por -- minuto sin ninguna suscripción real). CREATE OR ALTER PROCEDURE [dbo].[SP_Webhook_CaptureEvent] @object_type NVARCHAR(20), @transaction_type NCHAR(1), @num_of_cols_in_key INT, @list_of_key_cols_tab_del NVARCHAR(255), @list_of_cols_val_tab_del NVARCHAR(255), @error INT OUTPUT, @error_message NVARCHAR(200) OUTPUT AS BEGIN SET @error = 0 SET @error_message = N'Ok' DECLARE @code NVARCHAR(36) = CONVERT(NVARCHAR(36), NEWID()) DECLARE @isOwnTableEcho BIT = CASE WHEN @object_type LIKE '-%' + CHAR(9) + '@OEVC' THEN 1 WHEN @object_type LIKE '-%' + CHAR(9) + '@EVC1' THEN 1 WHEN @object_type LIKE '-%' + CHAR(9) + '@OEVN' THEN 1 WHEN @object_type LIKE '-%' + CHAR(9) + '@EVN1' THEN 1 ELSE 0 END DECLARE @hasActiveSubscription BIT = CASE WHEN EXISTS ( SELECT 1 FROM [dbo].[@EVC1] f INNER JOIN [dbo].[@OEVC] s ON s.Code = f.U_WebhookID WHERE f.U_ObjectType = @object_type AND f.U_TransType = @transaction_type AND s.U_State = 'A' ) THEN 1 ELSE 0 END -- Solo inserta si no es un eco de nuestras propias tablas (arriba) y -- si hay una suscripción activa interesada en este ObjectType+TransType. IF @isOwnTableEcho = 0 AND @hasActiveSubscription = 1 BEGIN BEGIN TRY INSERT INTO [dbo].[@OEVN] ( Code, Name, U_SourceDB, U_Status, U_ObjectType, U_TransType, U_FieldsInKe, U_FieldNames, U_FieldValue, U_ReplayStat ) VALUES ( @code, @code, DB_NAME(), 'N', @object_type, @transaction_type, @num_of_cols_in_key, @list_of_key_cols_tab_del, @list_of_cols_val_tab_del, 'N' ) END TRY BEGIN CATCH SET @error = ERROR_NUMBER() SET @error_message = LEFT(ERROR_MESSAGE(), 200) END CATCH END END GO