Saltar al contenido

Configurar sincronización bidireccional entre dos sistemas en Jitterbit Studio

Introducción

La sincronización bidireccional mantiene los registros consistentes entre dos sistemas separados propagando cambios en cualquier dirección: las actualizaciones realizadas en el sistema A se escriben en el sistema B, y las actualizaciones realizadas en el sistema B se escriben de vuelta en el sistema A.

El desafío principal es evitar bucles infinitos. Cuando Studio escribe un registro en el sistema B, la detección de cambios del sistema B ve ese registro como una nueva modificación y (sin una salvaguarda) desencadena la sincronización de B a A, que escribe el registro de vuelta en el sistema A, lo que luego desencadena la sincronización de A a B nuevamente. Un campo de bandera de sincronización en los registros de cada sistema es la forma más confiable de romper este ciclo: cada dirección de sincronización marca los registros que escribe como "sincronizados por Jitterbit", y la dirección opuesta filtra esos registros de sus consultas.

Esta guía utiliza Salesforce y NetSuite como los dos sistemas de ejemplo y asume familiaridad con la configuración de conexiones, transformaciones y scripts de Studio. Para obtener información sobre temas relacionados, consulta:

Patrón de diseño

El patrón utiliza dos cadenas de operaciones independientes:

%%{init: {"themeVariables": {"lineColor": "#6b7280", "edgeLabelBackground": "#f5f5f5"}}}%% flowchart LR A[Salesforce Query] --> B[Transformation] --> C[NetSuite Upsert] --> D[Script] E[NetSuite Search] --> F[Transformation] --> G[Salesforce Upsert] --> H[Script]

Dos campos booleanos personalizados llevan el estado de sincronización, uno en cada sistema externo:

  • Salesforce: Jitterbit_Synced__c: false cuando un usuario modificó por última vez el registro; true cuando Studio escribió por última vez el registro.
  • NetSuite: custbody_jb_synced: la misma semántica.

Cada sistema también requiere una regla de automatización que restablezca el campo a false cada vez que un usuario modifique un registro. Esto garantiza que los cambios iniciados por el usuario siempre se recojan en la siguiente ejecución de sincronización, mientras que los registros escritos por Studio se ignoren.

Cómo se previene el bucle:

  1. Un usuario modifica una cuenta en Salesforce. La regla de automatización establece Jitterbit_Synced__c = false.
  2. La cadena de Salesforce a NetSuite consulta registros donde Jitterbit_Synced__c = false y encuentra el registro modificado.
  3. Studio escribe el registro en NetSuite con custbody_jb_synced = true, luego establece Jitterbit_Synced__c = true de vuelta en Salesforce.
  4. La cadena de NetSuite a Salesforce consulta NetSuite para registros donde custbody_jb_synced = false. El registro del paso 3 se excluye, por lo que no se escribe de vuelta en Salesforce.

Requisitos previos

Antes de configurar las operaciones de Studio, completa los siguientes pasos en cada sistema externo.

En Salesforce

  1. En el objeto Account (u otro objeto que estés sincronizando), crea un campo de casilla de verificación personalizado con la etiqueta Jitterbit Synced y el nombre de API Jitterbit_Synced__c. Establece el valor predeterminado como Unchecked.

  2. Crea una regla de flujo de trabajo o un flujo de Process Builder que se active en la creación o actualización de registros por un usuario y establezca Jitterbit_Synced__c en false. Esto garantiza que los cambios iniciados por el usuario sean visibles para la cadena de Salesforce a NetSuite.

En NetSuite

  1. En el tipo de registro Customer (u otro tipo de registro que estés sincronizando), crea un campo de casilla de verificación personalizado con la etiqueta Jitterbit Synced e ID custbody_jb_synced. Establece el valor predeterminado como unchecked.

  2. Crea un SuiteScript de evento de usuario (afterSubmit) que se active al guardar el registro y establezca custbody_jb_synced = false. Utiliza context.type para omitir la ejecución cuando el script guarda el registro (como una escritura de sincronización de Jitterbit), de modo que solo los guardados por usuario restablezcan la bandera.

En tu proyecto de Jitterbit

Crea dos variables de proyecto para rastrear la última hora de sincronización exitosa para cada dirección:

  • sf_last_sync_time: la última vez que la cadena de Salesforce a NetSuite se ejecutó correctamente. Establece un valor inicial de una fecha en el pasado, por ejemplo 2020-01-01T00:00:00Z.
  • ns_last_sync_time: la última vez que la cadena de NetSuite a Salesforce se ejecutó correctamente. Establece el mismo valor inicial.

Parte 1: Configurar la cadena de operaciones de Salesforce a NetSuite

Paso 1: Configurar la actividad Salesforce Query

  1. En el lienzo de diseño, arrastra una actividad Salesforce Query desde un endpoint Salesforce existente al lienzo para iniciar la cadena.

  2. Haz doble clic en la actividad para abrir su configuración.

  3. Nombre: Ingresa Query Salesforce Accounts.

  4. Objeto: Selecciona Account.

  5. Condiciones de consulta: Agrega dos condiciones:

    • Jitterbit_Synced__c es igual a false
    • LastModifiedDate mayor que $sf_last_sync_time

    En conjunto, estas condiciones devuelven solo los registros modificados por usuarios desde la última ejecución de sincronización.

  6. Selecciona los campos a devolver: Id, Name y cualquier otro campo que se asigne a NetSuite.

  7. Haz clic en Finalizado.

Paso 2: Configurar la transformación

  1. Agrega un paso de Transformación después de la actividad Salesforce Query.

  2. Establece el esquema de origen en la respuesta de Salesforce Query y el esquema de destino en la estructura de registro de NetSuite Customer.

  3. Asigna los campos de origen de Salesforce a los campos de destino correspondientes en NetSuite.

  4. Agrega un script a nivel raíz (fuera del nodo de bucle) que marque cada registro escrito como "sincronizado por Jitterbit" y capture el tiempo de ejecución actual:

    target.custbody_jb_synced = true;
    $sync_run_time = Now();
    

    Establecer custbody_jb_synced = true en cada registro de NetSuite escrito por esta cadena es lo que impide que la cadena NetSuite-a-Salesforce los detecte y los escriba nuevamente.

  5. En el mismo script a nivel raíz, agrega el ID de cada registro de origen a una variable global para que el script posterior a la sincronización pueda actualizar Salesforce:

    $synced_sf_ids = $synced_sf_ids + If(Length($synced_sf_ids) > 0, ",", "") + Source.Id;
    

Paso 3: Configurar la actividad NetSuite Upsert

  1. Agrega una actividad NetSuite Upsert después de la transformación.

  2. Nombre: Ingresa Upsert NetSuite Customers.

  3. Tipo de registro: Selecciona Customer.

  4. Campo de ID externo: Selecciona el campo que almacena el ID de registro de Salesforce en NetSuite (por ejemplo, custentity_sf_id). Este campo es la clave de upsert: si existe un registro coincidente, se actualiza; de lo contrario, se crea un nuevo registro.

  5. Haz clic en Finalizado.

Paso 4: Escribir el script posterior a la sincronización

Después de hacer un upsert a NetSuite, actualiza Salesforce para marcar los mismos registros como procesados. Esto evita que se vuelvan a consultar en la siguiente ejecución.

  1. Agrega un paso de Script después de la actividad NetSuite Upsert.

  2. Ingresa lo siguiente:

    // Mark the synced Salesforce records so the next run skips them.
    // $synced_sf_ids is a comma-separated list of Salesforce IDs built in the transformation.
    RunOperation("<TAG>operation:Mark Salesforce Records Synced</TAG>");
    
    // Advance the last-sync timestamp so the next query picks up only newer changes.
    $sf_last_sync_time = $sync_run_time;
    SetVar("sf_last_sync_time", $sf_last_sync_time);
    
    // Reset for the next run.
    $synced_sf_ids = "";
    
  3. Crea una operación separada llamada Mark Salesforce Records Synced que contenga una actividad Salesforce Update. Configura la actividad para establecer Jitterbit_Synced__c = true en cada ID de registro en synced_sf_ids. Utiliza una transformación que divida synced_sf_ids en comas y asigne cada ID a una carga útil de actualización.

  4. También inicializa $synced_sf_ids = "" al principio de cualquier script de controlador que llame a esta cadena, para que la lista de IDs esté vacía al inicio de cada ejecución.

Parte 2: Configurar la cadena de operaciones NetSuite-a-Salesforce

La cadena NetSuite-a-Salesforce sigue la misma estructura que la Parte 1 con los sistemas de origen y destino intercambiados.

Paso 1: Configurar la actividad NetSuite Search

  1. Arrastra una actividad NetSuite Search al lienzo.

  2. Nombre: Ingresa Search NetSuite Customers.

  3. Filtro de búsqueda: Agrega dos condiciones:

    • custbody_jb_synced es false
    • lastmodifieddate después de $ns_last_sync_time
  4. Campos a devolver: Selecciona internalId, entityId, custentity_sf_id y cualquier otro campo que se asigne a Salesforce.

  5. Haz clic en Finalizado.

Paso 2: Configurar la transformación

  1. Agrega un paso de Transformación después de la actividad NetSuite Search.

  2. Establece el esquema de origen en la respuesta de NetSuite Search y el esquema de destino en la estructura Salesforce Account.

  3. Asigna los campos de origen de NetSuite a los campos de destino correspondientes en Salesforce.

  4. Añade un script a nivel raíz que marque cada registro de Salesforce como "sincronizado por Jitterbit" y recopile las IDs de NetSuite para la actualización posterior a la sincronización:

    target.Jitterbit_Synced__c = true;
    $sync_run_time = Now();
    $synced_ns_ids = $synced_ns_ids + If(Length($synced_ns_ids) > 0, ",", "") + Source.internalId;
    

Paso 3: Configura la actividad de Upsert de Salesforce

  1. Añade una actividad Upsert de Salesforce después de la transformación.

  2. Nombre: Ingresa Upsert Salesforce Accounts.

  3. Campo de ID externo: Selecciona el campo que almacena la ID interna de NetSuite en Salesforce (por ejemplo, NetSuite_ID__c).

  4. Haz clic en Finished.

Paso 4: Escribe el script posterior a la sincronización

  1. Añade un paso Script después de la actividad Upsert de Salesforce.

  2. Ingresa lo siguiente:

    RunOperation("<TAG>operation:Mark NetSuite Records Synced</TAG>");
    
    $ns_last_sync_time = $sync_run_time;
    SetVar("ns_last_sync_time", $ns_last_sync_time);
    
    $synced_ns_ids = "";
    
  3. Crea una operación separada llamada Mark NetSuite Records Synced que contenga una actividad Update de NetSuite que establezca custbody_jb_synced = true en cada ID de registro en synced_ns_ids.

Parte 3: Programa las operaciones

Ambas cadenas se ejecutan en programas de operación. Para reducir la posibilidad de que ambas cadenas se ejecuten simultáneamente y recojan escrituras en curso una de la otra, desfasa sus horas de inicio.

  1. Asigna un programa a la cadena de Salesforce a NetSuite. Para un intervalo de sincronización de 15 minutos, configúralo para que se ejecute a los 0, 15, 30 y 45 minutos de cada hora.

  2. Asigna un programa a la cadena de NetSuite a Salesforce y desfásalo por la mitad del intervalo (por ejemplo, 7, 22, 37 y 52 minutos de cada hora).

Para obtener instrucciones paso a paso sobre cómo crear y asignar programas, consulta Programa una operación para que se ejecute automáticamente.

Nota

Desfasar reduce la superposición pero no la elimina. Si una ejecución de sincronización toma más tiempo que el intervalo de desfase, ambas cadenas pueden ejecutarse simultáneamente. Para sincronizaciones de alto volumen, considera añadir un bloqueo: al inicio de cada cadena, lee una variable de proyecto o una entrada de Cloud Datastore llamada sync_lock. Si el bloqueo está establecido, sal temprano usando RaiseError. De lo contrario, establece el bloqueo antes de proceder y límpialo en el script posterior a la sincronización.

Verifica la integración

  1. Implementa y ejecuta la cadena de Salesforce a NetSuite manualmente.

  2. En los registros de operación, confirma que los registros se recuperaron de Salesforce y se escribieron en NetSuite.

  3. En NetSuite, abre uno de los registros de cliente sincronizados y confirma que custbody_jb_synced esté marcado.

  4. En Salesforce, abre la cuenta correspondiente y confirma que Jitterbit_Synced__c esté marcado.

  5. Ejecuta la cadena de NetSuite a Salesforce. En los registros, confirma que los registros de cliente escritos en el paso 2 no aparezcan en los resultados de búsqueda de NetSuite. Esto confirma que el filtro de prevención de bucles está funcionando: los registros con custbody_jb_synced = true se excluyen.

  6. En NetSuite, modifica directamente uno de los registros de cliente sincronizados. El SuiteScript afterSubmit restablece custbody_jb_synced = false. Ejecuta la cadena de NetSuite a Salesforce y confirma que el cambio se propague a Salesforce.

  7. En Salesforce, confirma que la cuenta actualizada tenga Jitterbit_Synced__c = true después de la sincronización. Ejecuta la cadena de Salesforce a NetSuite y confirma que el registro no aparezca en los resultados de la consulta, ya que Jitterbit lo escribió por última vez.

Para un enfoque alternativo para detectar registros cambiados sin campos de marca de sincronización, consulta Detecta y desduplica registros usando funciones hash.